From 53a95476705a2ae17610ef7e175c4916f6975853 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Tue, 8 Aug 2023 13:54:40 -0500 Subject: [PATCH 01/49] Initial commit --- .gitignore | 32 ++++++++++++++++++++++++++++++++ LICENSE | 21 +++++++++++++++++++++ README.md | 1 + 3 files changed, 54 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..259148fa18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..9f5c6dea78 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 ROCm Developer Tools + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..8f8bcf1a62 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# rocprofiler-register \ No newline at end of file From fa4295db6b8c0c3b091aec8d8dffc6dffcd4754b Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Thu, 17 Aug 2023 14:59:24 -0500 Subject: [PATCH 02/49] Initial Implementation: include (#10) * Initial Implementation: include * Initial Implementation: lib details (#11) * Initial Implementation: lib details * Initial Implementation: lib (#12) * Initial Implementation: lib * Initial Implementation: source (#13) * Initial Implementation: source * Initial Implementation: samples (#14) * Initial Implementation: samples * Initial Implementation: tests (#15) * Initial Implementation: tests * Initial Implementation: scripts (#16) * Initial Implementation: scripts * Initial Implementation: cmake (#17) * Initial Implementation: cmake * Initial Implementation: top-level files (#18) * Initial Implementation: top-level files - clang-format - clang-tidy - cmake-format - ignore build and cache directories - main CMakeLists.txt - pyproject.toml (python formatting) - VERSION file * Initial Implementation: workflow (#19) * Fix unused variable - rocprofiler_register_warn_level --- .clang-format | 114 +++ .clang-tidy | 55 + .cmake-format.yaml | 318 ++++++ .github/workflows/continuous-integration.yml | 172 ++++ .github/workflows/formatting.yml | 146 +++ .gitignore | 4 + CMakeLists.txt | 110 ++ VERSION | 1 + cmake/Templates/modulefile.in | 16 + .../rocprofiler-register-config.cmake.in | 32 + cmake/Templates/setup-env.sh.in | 23 + .../rocprofiler_register_build_settings.cmake | 107 ++ cmake/rocprofiler_register_compilers.cmake | 352 +++++++ .../rocprofiler_register_config_install.cmake | 87 ++ ...cprofiler_register_config_interfaces.cmake | 67 ++ ...ocprofiler_register_config_packaging.cmake | 100 ++ cmake/rocprofiler_register_formatting.cmake | 104 ++ cmake/rocprofiler_register_interfaces.cmake | 34 + cmake/rocprofiler_register_linting.cmake | 47 + cmake/rocprofiler_register_memcheck.cmake | 40 + cmake/rocprofiler_register_options.cmake | 90 ++ cmake/rocprofiler_register_utilities.cmake | 941 ++++++++++++++++++ pyproject.toml | 25 + samples/CMakeLists.txt | 6 + samples/library-implementation/CMakeLists.txt | 18 + samples/library-implementation/demo.cpp | 120 +++ samples/library-implementation/demo.hpp | 37 + scripts/address-sanitizer-suppr.txt | 3 + scripts/leak-sanitizer-suppr.txt | 3 + scripts/run-ci.py | 463 +++++++++ scripts/thread-sanitizer-suppr.txt | 3 + source/CMakeLists.txt | 11 + source/include/CMakeLists.txt | 4 + .../rocprofiler-register/CMakeLists.txt | 13 + .../rocprofiler-register.h | 188 ++++ .../include/rocprofiler-register/version.h.in | 103 ++ source/lib/CMakeLists.txt | 4 + .../lib/rocprofiler-register/CMakeLists.txt | 36 + .../details/CMakeLists.txt | 10 + .../lib/rocprofiler-register/details/dl.cpp | 125 +++ .../lib/rocprofiler-register/details/dl.hpp | 60 ++ .../details/environment.hpp | 191 ++++ .../lib/rocprofiler-register/details/join.hpp | 184 ++++ .../lib/rocprofiler-register/details/log.hpp | 518 ++++++++++ .../rocprofiler-register/details/utility.cpp | 127 +++ .../rocprofiler-register/details/utility.hpp | 44 + .../rocprofiler_register.c | 24 + .../rocprofiler_register.cpp | 374 +++++++ tests/CMakeLists.txt | 465 +++++++++ tests/amdhip/CMakeLists.txt | 39 + tests/amdhip/amdhip.cpp | 154 +++ tests/amdhip/amdhip.hpp | 40 + tests/common/fwd.h | 31 + tests/common/fwd.hpp | 101 ++ tests/hsa-runtime/CMakeLists.txt | 35 + tests/hsa-runtime/hsa-runtime.cpp | 149 +++ tests/hsa-runtime/hsa-runtime.hpp | 40 + tests/rocprofiler/CMakeLists.txt | 14 + tests/rocprofiler/rocprofiler.cpp | 135 +++ tests/roctx/CMakeLists.txt | 19 + tests/roctx/roctx.cpp | 170 ++++ tests/roctx/roctx.hpp | 46 + tests/start-up-test/CMakeLists.txt | 3 + tests/test-amdhip-ctor-mt.cpp | 72 ++ tests/test-amdhip-ctor.cpp | 42 + tests/test-amdhip-hsart-roctx.cpp | 43 + tests/test-amdhip-roctx-mt.cpp | 72 ++ tests/test-amdhip-roctx.cpp | 43 + 68 files changed, 7367 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .cmake-format.yaml create mode 100644 .github/workflows/continuous-integration.yml create mode 100644 .github/workflows/formatting.yml create mode 100644 CMakeLists.txt create mode 100644 VERSION create mode 100644 cmake/Templates/modulefile.in create mode 100644 cmake/Templates/rocprofiler-register-config.cmake.in create mode 100644 cmake/Templates/setup-env.sh.in create mode 100644 cmake/rocprofiler_register_build_settings.cmake create mode 100644 cmake/rocprofiler_register_compilers.cmake create mode 100644 cmake/rocprofiler_register_config_install.cmake create mode 100644 cmake/rocprofiler_register_config_interfaces.cmake create mode 100644 cmake/rocprofiler_register_config_packaging.cmake create mode 100644 cmake/rocprofiler_register_formatting.cmake create mode 100644 cmake/rocprofiler_register_interfaces.cmake create mode 100644 cmake/rocprofiler_register_linting.cmake create mode 100644 cmake/rocprofiler_register_memcheck.cmake create mode 100644 cmake/rocprofiler_register_options.cmake create mode 100644 cmake/rocprofiler_register_utilities.cmake create mode 100644 pyproject.toml create mode 100644 samples/CMakeLists.txt create mode 100644 samples/library-implementation/CMakeLists.txt create mode 100644 samples/library-implementation/demo.cpp create mode 100644 samples/library-implementation/demo.hpp create mode 100644 scripts/address-sanitizer-suppr.txt create mode 100644 scripts/leak-sanitizer-suppr.txt create mode 100755 scripts/run-ci.py create mode 100644 scripts/thread-sanitizer-suppr.txt create mode 100644 source/CMakeLists.txt create mode 100644 source/include/CMakeLists.txt create mode 100644 source/include/rocprofiler-register/CMakeLists.txt create mode 100644 source/include/rocprofiler-register/rocprofiler-register.h create mode 100644 source/include/rocprofiler-register/version.h.in create mode 100644 source/lib/CMakeLists.txt create mode 100644 source/lib/rocprofiler-register/CMakeLists.txt create mode 100644 source/lib/rocprofiler-register/details/CMakeLists.txt create mode 100644 source/lib/rocprofiler-register/details/dl.cpp create mode 100644 source/lib/rocprofiler-register/details/dl.hpp create mode 100644 source/lib/rocprofiler-register/details/environment.hpp create mode 100644 source/lib/rocprofiler-register/details/join.hpp create mode 100644 source/lib/rocprofiler-register/details/log.hpp create mode 100644 source/lib/rocprofiler-register/details/utility.cpp create mode 100644 source/lib/rocprofiler-register/details/utility.hpp create mode 100644 source/lib/rocprofiler-register/rocprofiler_register.c create mode 100644 source/lib/rocprofiler-register/rocprofiler_register.cpp create mode 100644 tests/CMakeLists.txt create mode 100644 tests/amdhip/CMakeLists.txt create mode 100644 tests/amdhip/amdhip.cpp create mode 100644 tests/amdhip/amdhip.hpp create mode 100644 tests/common/fwd.h create mode 100644 tests/common/fwd.hpp create mode 100644 tests/hsa-runtime/CMakeLists.txt create mode 100644 tests/hsa-runtime/hsa-runtime.cpp create mode 100644 tests/hsa-runtime/hsa-runtime.hpp create mode 100644 tests/rocprofiler/CMakeLists.txt create mode 100644 tests/rocprofiler/rocprofiler.cpp create mode 100644 tests/roctx/CMakeLists.txt create mode 100644 tests/roctx/roctx.cpp create mode 100644 tests/roctx/roctx.hpp create mode 100644 tests/start-up-test/CMakeLists.txt create mode 100644 tests/test-amdhip-ctor-mt.cpp create mode 100644 tests/test-amdhip-ctor.cpp create mode 100644 tests/test-amdhip-hsart-roctx.cpp create mode 100644 tests/test-amdhip-roctx-mt.cpp create mode 100644 tests/test-amdhip-roctx.cpp diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..8293545c39 --- /dev/null +++ b/.clang-format @@ -0,0 +1,114 @@ +# clang-format v11 +--- +Language: Cpp +BasedOnStyle: Google +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: true +AlignConsecutiveBitFields: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: TopLevel +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: true +BreakInheritanceList: BeforeComma +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakStringLiterals: true +ColumnLimit: 90 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: true +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeBlocks: Preserve +IndentCaseLabels: true +IndentCaseBlocks: false +IndentFunctionDeclarationAfterType: false +IndentGotoLabels: true +IndentPPDirectives: AfterHash +IndentExternBlock: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: Never +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Auto +TabWidth: 4 +UseTab: Never +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000000..7714903656 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,55 @@ +--- +Checks: "-*,\ +misc-*,\ +-misc-incorrect-roundings,\ +-misc-macro-parentheses,\ +-misc-misplaced-widening-cast,\ +-misc-static-assert,\ +-misc-no-recursion,\ +-misc-non-private-member-variables-in-classes,\ +-misc-include-cleaner,\ +-misc-const-correctness,\ +modernize-*,\ +-modernize-deprecated-headers,\ +-modernize-raw-string-literal,\ +-modernize-return-braced-init-list,\ +-modernize-use-transparent-functors,\ +-modernize-use-trailing-return-type,\ +-modernize-avoid-c-arrays,\ +-modernize-redundant-void-arg,\ +-modernize-use-using,\ +-modernize-use-auto,\ +-modernize-concat-nested-namespaces,\ +-modernize-use-nodiscard,\ +-modernize-macro-to-enum,\ +-modernize-type-traits,\ +performance-*,\ +readability-*,\ +-readability-function-size,\ +-readability-identifier-naming,\ +-readability-implicit-bool-cast,\ +-readability-inconsistent-declaration-parameter-name,\ +-readability-named-parameter,\ +-readability-magic-numbers,\ +-readability-redundant-declaration,\ +-readability-redundant-member-init,\ +-readability-simplify-boolean-expr,\ +-readability-uppercase-literal-suffix,\ +-readability-braces-around-statements,\ +-readability-avoid-const-params-in-decls,\ +-readability-else-after-return,\ +-readability-isolate-declaration,\ +-readability-redundant-string-cstr,\ +-readability-static-accessed-through-instance,\ +-readability-const-return-type,\ +-readability-redundant-access-specifiers,\ +-readability-function-cognitive-complexity,\ +-readability-identifier-length,\ +-readability-use-anyofallof,\ +" +CheckOptions: + - key: readability-braces-around-statements.ShortStatementLines + value: '2' + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: '1' +... diff --git a/.cmake-format.yaml b/.cmake-format.yaml new file mode 100644 index 0000000000..61a2cd0e93 --- /dev/null +++ b/.cmake-format.yaml @@ -0,0 +1,318 @@ +parse: + additional_commands: + rocprofiler_register_checkout_git_submodule: + flags: + - RECURSIVE + kwargs: + RELATIVE_PATH: '*' + WORKING_DIRECTORY: '*' + TEST_FILE: '*' + REPO_URL: '*' + REPO_BRANCH: '*' + ADDITIONAL_COMMANDS: '*' + rocprofiler_register_save_variables: + kwargs: + VARIABLES: '*' + CONDITION: '*' + rocprofiler_register_restore_variables: + kwargs: + VARIABLES: '*' + CONDITION: '*' + rocprofiler_register_target_compile_options: + flags: + - BUILD_INTERFACE + - FORCE + kwargs: + PUBLIC: '*' + PRIVATE: '*' + INTERFACE: '*' + LANGUAGES: '*' + LINK_LANGUAGES: '*' + rocprofiler_register_add_test: + flags: + - SKIP_BASELINE + - SKIP_SAMPLING + - SKIP_REWRITE + - SKIP_RUNTIME + kwargs: + NAME: '*' + TARGET: '*' + MPI: '*' + GPU: '*' + NUM_PROCS: '*' + REWRITE_TIMEOUT: '*' + RUNTIME_TIMEOUT: '*' + SAMPLING_TIMEOUT: '*' + SAMPLING_ARGS: '*' + REWRITE_ARGS: '*' + RUNTIME_ARGS: '*' + RUN_ARGS: '*' + ENVIRONMENT: '*' + LABELS: '*' + PROPERTIES: '*' + SAMPLING_PASS_REGEX: '*' + SAMPLING_FAIL_REGEX: '*' + RUNTIME_PASS_REGEX: '*' + RUNTIME_FAIL_REGEX: '*' + REWRITE_PASS_REGEX: '*' + REWRITE_FAIL_REGEX: '*' + BASELINE_PASS_REGEX: '*' + BASELINE_FAIL_REGEX: '*' + REWRITE_RUN_PASS_REGEX: '*' + REWRITE_RUN_FAIL_REGEX: '*' + rocprofiler_register_add_causal_test: + flags: + - SKIP_BASELINE + kwargs: + NAME: '*' + TARGET: '*' + CAUSAL_TIMEOUT: '*' + CAUSAL_VALIDATE_TIMEOUT: '*' + CAUSAL_MODE: '*' + CAUSAL_ARGS: '*' + CAUSAL_VALIDATE_ARGS: '*' + RUNTIME_ARGS: '*' + RUN_ARGS: '*' + ENVIRONMENT: '*' + LABELS: '*' + PROPERTIES: '*' + CAUSAL_PASS_REGEX: '*' + CAUSAL_FAIL_REGEX: '*' + BASELINE_PASS_REGEX: '*' + BASELINE_FAIL_REGEX: '*' + CAUSAL_VALIDATE_PASS_REGEX: '*' + CAUSAL_VALIDATE_FAIL_REGEX: '*' + rocprofiler_register_target_compile_definitions: + kwargs: + PUBLIC: '*' + PRIVATE: '*' + INTERFACE: '*' + rocprofiler_register_add_bin_test: + flags: + - WILL_FAIL + kwargs: + NAME: '*' + ARGS: '*' + LABELS: '*' + TARGET: '*' + DEPENDS: '*' + COMMAND: '*' + TIMEOUT: '*' + PROPERTIES: '*' + ENVIRONMENT: '*' + WORKING_DIRECTORY: '*' + PASS_REGEX: '*' + FAIL_REGEX: '*' + SKIP_REGEX: '*' + rocprofiler_register_add_python_test: + flags: + - STANDALONE + kwargs: + NAME: '*' + FILE: '*' + TIMEOUT: '*' + PROFILE_ARGS: '*' + RUN_ARGS: '*' + ENVIRONMENT: '*' + LABELS: '*' + DEPENDS: '*' + COMMAND: '*' + PROPERTIES: '*' + PYTHON_EXECUTABLE: '*' + PYTHON_VERSION: '*' + PASS_REGEX: '*' + FAIL_REGEX: '*' + SKIP_REGEX: '*' + rocprofiler_register_add_python_validation_test: + kwargs: + NAME: '*' + ARGS: '*' + PERFETTO_FILE: '*' + PERFETTO_METRIC: '*' + TIMEMORY_FILE: '*' + TIMEMORY_METRIC: '*' + rocm_version_message: + flags: + - STATUS + - WARNING + - SEND_ERROR + - FATAL_ERROR + - AUTHOR_WARNING + rocprofiler_register_find_python: + flags: + - REQUIRED + - QUIET + kwargs: + VERSION: '*' + ROOT_DIR: '*' + COMPONENTS: '*' + rocprofiler_register_python_console_script: + kwargs: + VERSION: '*' + ROOT_DIR: '*' + rocprofiler_register_pybind11_add_module: + flags: + - MODULE + - SHARED + - EXCLUDE_FROM_ALL + - NO_EXTRAS + - SYSTEM + - THIN_LTO + - LTO + kwargs: + PYTHON_VERSION: '*' + CXX_STANDARD: '*' + VISIBILITY: '*' + rocprofiler_register_directory: + flags: + - MKDIR + - FAIL + kwargs: + PREFIX: '*' + OUTPUT_VARIABLE: '*' + WORKING_DIRECTORY: '*' + PATHS: '*' + rocprofiler_register_check_python_dirs_and_versions: + flags: + - UNSET + - FAIL + kwargs: + RESULT_VARIABLE: '*' + OUTPUT_VARIABLE: '*' + rocprofiler_register_find_static_library: + flags: + - NO_CACHE + - REQUIRED + - NO_DEFAULT_PATH + - NO_PACKAGE_ROOT_PATH + - NO_CMAKE_PATH + - NO_CMAKE_ENVIRONMENT_PATH + - NO_SYSTEM_ENVIRONMENT_PATH + - CMAKE_FIND_ROOT_PATH_BOTH + - ONLY_CMAKE_FIND_ROOT_PATH + - NO_CMAKE_FIND_ROOT_PATH + kwargs: + NAMES: '*' + NAMES_PER_DIR: '*' + HINTS: '*' + PATHS: '*' + PATH_SUFFIXES: '*' + DOC: '*' + rocprofiler_register_find_shared_library: + flags: + - NO_CACHE + - REQUIRED + - NO_DEFAULT_PATH + - NO_PACKAGE_ROOT_PATH + - NO_CMAKE_PATH + - NO_CMAKE_ENVIRONMENT_PATH + - NO_SYSTEM_ENVIRONMENT_PATH + - CMAKE_FIND_ROOT_PATH_BOTH + - ONLY_CMAKE_FIND_ROOT_PATH + - NO_CMAKE_FIND_ROOT_PATH + kwargs: + NAMES: '*' + NAMES_PER_DIR: '*' + HINTS: '*' + PATHS: '*' + PATH_SUFFIXES: '*' + DOC: '*' + rocprofiler_register_causal_example_executable: + kwargs: + TAG: '*' + SOURCES: '*' + DEFINITIONS: '*' + LINK_LIBRARIES: '*' + INCLUDE_DIRECTORIES: '*' + rocprofiler_register_add_validation_test: + kwargs: + NAME: '*' + ARGS: '*' + LABELS: '*' + TIMEOUT: '*' + DEPENDS: '*' + PROPERTIES: '*' + PASS_REGEX: '*' + FAIL_REGEX: '*' + SKIP_REGEX: '*' + ENVIRONMENT: '*' + PERFETTO_FILE: '*' + PERFETTO_METRIC: '*' + TIMEMORY_FILE: '*' + TIMEMORY_METRIC: '*' + rocp_register_test_executable: + kwargs: + SECURE: '*' + SOURCES: '*' + LIBRARIES: '*' + CORE_PASS_REGEX: '*' + CORE_FAIL_REGEX: '*' + PRELOAD_PASS_REGEX: '*' + PRELOAD_FAIL_REGEX: '*' + WRAP_PASS_REGEX: '*' + WRAP_FAIL_REGEX: '*' + PRELOAD_WRAP_PASS_REGEX: '*' + PRELOAD_WRAP_FAIL_REGEX: '*' + override_spec: {} + vartags: [] + proptags: [] +format: + disable: false + line_width: 90 + tab_size: 4 + use_tabchars: false + fractional_tab_policy: use-space + max_subgroups_hwrap: 2 + max_pargs_hwrap: 8 + max_rows_cmdline: 2 + separate_ctrl_name_with_space: false + separate_fn_name_with_space: false + dangle_parens: false + dangle_align: child + min_prefix_chars: 4 + max_prefix_chars: 10 + max_lines_hwrap: 2 + line_ending: unix + command_case: lower + keyword_case: upper + always_wrap: [] + enable_sort: true + autosort: false + require_valid_layout: false + layout_passes: {} +markup: + bullet_char: '*' + enum_char: . + first_comment_is_literal: true + literal_comment_pattern: ^# + fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$ + ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$ + explicit_trailing_pattern: '#<' + hashruler_min_length: 10 + canonicalize_hashrulers: true + enable_markup: true +lint: + disabled_codes: [] + function_pattern: '[0-9a-z_]+' + macro_pattern: '[0-9A-Z_]+' + global_var_pattern: '[A-Z][0-9A-Z_]+' + internal_var_pattern: _[A-Z][0-9A-Z_]+ + local_var_pattern: '[a-z][a-z0-9_]+' + private_var_pattern: _[0-9a-z_]+ + public_var_pattern: '[A-Z][0-9A-Z_]+' + argument_var_pattern: '[a-z][a-z0-9_]+' + keyword_pattern: '[A-Z][0-9A-Z_]+' + max_conditionals_custom_parser: 2 + min_statement_spacing: 1 + max_statement_spacing: 2 + max_returns: 6 + max_branches: 12 + max_arguments: 5 + max_localvars: 15 + max_statements: 50 +encode: + emit_byteorder_mark: false + input_encoding: utf-8 + output_encoding: utf-8 +misc: + per_command: {} diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 0000000000..4959f58ee0 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,172 @@ +name: Continuous Integration + +on: + push: + branches: [ main, develop ] + paths-ignore: + - '*.md' + pull_request: + branches: [ main, develop ] + paths-ignore: + - '*.md' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ci: + strategy: + fail-fast: false + matrix: + runner: ['ubuntu-latest'] + compiler: ['clang-13', 'clang-14', 'clang-15', 'gcc-11', 'gcc-12'] + ci-args: [''] + ci-tag: [''] + include: + - runner: 'ubuntu-latest' + compiler: 'gcc-12' + ci-args: '--coverage' + ci-tag: '-codecov' + - runner: 'ubuntu-latest' + compiler: 'clang-15' + ci-args: '--linter clang-tidy' + ci-tag: '-clang-tidy' + # - runner: 'ubuntu-latest' + # compiler: 'gcc-12' + # ci-args: '--memcheck ThreadSanitizer' + # ci-tag: '-thread-sanitizer' + # - runner: 'ubuntu-latest' + # compiler: 'gcc-12' + # ci-args: '--memcheck AddressSanitizer' + # ci-tag: '-address-sanitizer' + # - runner: 'ubuntu-latest' + # compiler: 'gcc-12' + # ci-args: '--memcheck LeakSanitizer' + # ci-tag: '-leak-sanitizer' + # - runner: 'ubuntu-latest' + # compiler: 'gcc-12' + # ci-args: '--memcheck UndefinedBehaviorSanitizer' + # ci-tag: '-undefined-behavior-sanitizer' + + runs-on: ${{ matrix.runner }} + + env: + BUILD_TYPE: RelWithDebInfo + INSTALL_PREFIX: /opt/rocprofiler-register + PACKAGING_INSTALL_PREFIX: /opt/rocm + + steps: + - uses: actions/checkout@v3 + + - name: Install Packages + timeout-minutes: 25 + run: | + CC=${{ matrix.compiler }} && + CXX=$(echo ${{ matrix.compiler }} | sed 's/clang-/clang++-/1' | sed 's/gcc-/g++-/1') && + sudo apt-get update && + sudo apt-get install -y build-essential python3 environment-modules ${{ matrix.compiler }} ${CXX} && + sudo update-alternatives --install /usr/bin/cc cc /usr/bin/${CC} 100 && + sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/${CXX} 100 && + python3 -m pip install --upgrade pip && + python3 -m pip install 'cmake==3.21.4' + + - name: Setup GCov + timeout-minutes: 25 + if: ${{ matrix.compiler == 'gcc-12' }} + run: | + sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-12 100 + + - name: Setup Clang-Tidy + timeout-minutes: 25 + if: ${{ matrix.compiler == 'clang-15' }} + run: | + sudo apt-get install -y clang-tidy-15 + sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-15 100 + + - name: Configure, Build, and Test + timeout-minutes: 115 + shell: bash + run: + cmake --version && + python3 ./scripts/run-ci.py -B build + --name ${{ github.repository_owner }}-${{ github.ref_name }}-${{ matrix.runner }}-${{ matrix.compiler }}${{ matrix.ci-tag }} + --build-jobs 2 + --site GitHub + ${{ matrix.ci-args }} + --disable-cdash + -- + -DCMAKE_C_COMPILER=/usr/bin/cc + -DCMAKE_CXX_COMPILER=/usr/bin/c++ + -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} + -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_PREFIX }} + -DROCPROFILER_REGISTER_BUILD_TESTS=ON + -DROCPROFILER_REGISTER_BUILD_SAMPLES=ON + -- + -VV + + - name: Install + timeout-minutes: 10 + run: + cmake --build build --target install --parallel 2 + + - name: CPack and Install + run: | + cd build + cpack -G STGZ + mkdir -p ${{ env.PACKAGING_INSTALL_PREFIX }} + ./rocprofiler-register-*-Linux.sh --prefix=${{ env.PACKAGING_INSTALL_PREFIX }} --exclude-subdir --skip-license + + - name: Test Install Modulefile + timeout-minutes: 15 + shell: bash + run: | + set -v + source /usr/share/modules/init/$(basename ${SHELL}) + module use ${{ env.INSTALL_PREFIX }}/share/modulefiles + module avail + module load rocprofiler-register + pushd tests + BUILD_DIR=${PWD}/build-rocp-reg-modulefile + cmake -B ${BUILD_DIR} . + cmake --build ${BUILD_DIR} --target all + rm -rf ${BUILD_DIR} + + - name: Test Install Setup Env + timeout-minutes: 15 + shell: bash + run: | + set -v + source ${{ env.INSTALL_PREFIX }}/share/rocprofiler-register/setup-env.sh + pushd samples/library-implementation + BUILD_DIR=${PWD}/build-rocp-reg-setup-env + cmake -B ${BUILD_DIR} . + cmake --build ${BUILD_DIR} --target all + rm -rf ${BUILD_DIR} + + - name: Test Install CPack Modulefile + timeout-minutes: 15 + shell: bash + run: | + set -v + source /usr/share/modules/init/$(basename ${SHELL}) + module use ${{ env.PACKAGING_INSTALL_PREFIX }}/share/modulefiles + module avail + module load rocprofiler-register + pushd tests + BUILD_DIR=${PWD}/build-rocp-reg-modulefile-cpack + cmake -B ${BUILD_DIR} . + cmake --build ${BUILD_DIR} --target all + rm -rf ${BUILD_DIR} + + - name: Test Install CPack Setup Env + timeout-minutes: 15 + shell: bash + run: | + set -v + source ${{ env.PACKAGING_INSTALL_PREFIX }}/share/rocprofiler-register/setup-env.sh + pushd samples/library-implementation + BUILD_DIR=${PWD}/build-rocp-reg-setup-env-cpack + cmake -B ${BUILD_DIR} . + cmake --build ${BUILD_DIR} --target all + rm -rf ${BUILD_DIR} diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml new file mode 100644 index 0000000000..7cbbb93f75 --- /dev/null +++ b/.github/workflows/formatting.yml @@ -0,0 +1,146 @@ + +name: Formatting + +on: + workflow_dispatch: + pull_request: + branches: [ main ] + paths-ignore: + - '.github/workflows/pull_*.yml' + - '.github/workflows/linting.yml' + - '.github/workflows/markdown_lint.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + cmake: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v3 + + - name: Extract branch name + shell: bash + run: | + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y python3-pip + python3 -m pip install -U cmake-format + + - name: Run cmake-format + run: | + set +e + cmake-format -i $(find . -type f | egrep 'CMakeLists.txt|\.cmake$') + if [ $(git diff | wc -l) -ne 0 ]; then + echo -e "\nError! CMake code not formatted. Run cmake-format...\n" + echo -e "\nFiles:\n" + git diff --name-only + echo -e "\nFull diff:\n" + git diff + exit 1 + fi + + - name: Create pull request + if: failure() + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "cmake formatting (cmake-format)" + branch: ${{ steps.extract_branch.outputs.branch }}-cmake-format + delete-branch: true + title: "Format cmake code (via cmake-format) on ${{ steps.extract_branch.outputs.branch }}" + base: ${{ steps.extract_branch.outputs.branch }} + + source: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v3 + + - name: Install dependencies + run: | + DISTRIB_CODENAME=$(cat /etc/lsb-release | grep DISTRIB_CODENAME | awk -F '=' '{print $NF}') + sudo apt-get update + sudo apt-get install -y software-properties-common wget curl clang-format-11 + + - name: Extract branch name + shell: bash + run: | + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Run clang-format + run: | + set +e + FILES=$(find samples source tests -type f | egrep '\.(h|hpp|hh|c|cc|cpp)(|\.in)$') + FORMAT_OUT=$(clang-format-11 -i ${FILES}) + if [ $(git diff | wc -l) -ne 0 ]; then + echo -e "\nError! Code not formatted. Run clang-format (version 11)...\n" + echo -e "\nFiles:\n" + git diff --name-only + echo -e "\nFull diff:\n" + git diff + exit 1 + fi + + - name: Create pull request + if: failure() + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "source formatting (clang-format v11)" + branch: ${{ steps.extract_branch.outputs.branch }}-clang-format + delete-branch: true + title: "Format source code (via clang-format v11) on ${{ steps.extract_branch.outputs.branch }}" + base: ${{ steps.extract_branch.outputs.branch }} + + python: + runs-on: ubuntu-22.04 + strategy: + matrix: + python-version: ['3.10'] + + steps: + - uses: actions/checkout@v3 + + - name: Extract branch name + shell: bash + run: | + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install black + + - name: black format + run: | + black . + if [ $(git diff | wc -l) -ne 0 ]; then + echo -e "\nError! Python code not formatted. Run black...\n" + echo -e "\nFiles:\n" + git diff --name-only + echo -e "\nFull diff:\n" + git diff + exit 1 + fi + + - name: Create pull request + if: failure() + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "python formatting (black)" + branch: ${{ steps.extract_branch.outputs.branch }}-python-format + delete-branch: true + title: "Format python code (via black) on ${{ steps.extract_branch.outputs.branch }}" + base: ${{ steps.extract_branch.outputs.branch }} diff --git a/.gitignore b/.gitignore index 259148fa18..ff0a008fec 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ *.exe *.out *.app + +# Build directories +/build* +/.cache diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..ef4e70fe66 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,110 @@ +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND CMAKE_CURRENT_SOURCE_DIR STREQUAL + CMAKE_SOURCE_DIR) + set(MSG "") + message(STATUS "Warning! Building from the source directory is not recommended") + message(STATUS "If unintended, please remove 'CMakeCache.txt' and 'CMakeFiles'") + message(STATUS "and build from a separate directory") + message(AUTHOR_WARNING "In-source build") +endif() + +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" FULL_VERSION_STRING LIMIT_COUNT 1) +string(REGEX REPLACE "(\n|\r)" "" FULL_VERSION_STRING "${FULL_VERSION_STRING}") +string(REGEX REPLACE "([0-9]+)\.([0-9]+)\.([0-9]+)(.*)" "\\1.\\2.\\3" + ROCPROFILER_REGISTER_VERSION "${FULL_VERSION_STRING}") + +foreach(_LANG C CXX) + set(CMAKE_${_LANG}_FLAGS_COVERAGE_INIT + "-Og -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-inline-functions -fprofile-abs-path -fprofile-arcs -ftest-coverage --coverage" + CACHE STRING "${_LANG} flags for code coverage builds") + + set(CMAKE_${_LANG}_FLAGS_COVERAGE + "${CMAKE_${_LANG}_FLAGS_COVERAGE_INIT}" + CACHE STRING "${_LANG} flags for code coverage builds") +endforeach() + +project( + rocprofiler-register + LANGUAGES C CXX + VERSION ${ROCPROFILER_REGISTER_VERSION} + DESCRIPTION "Registration library for rocprofiler" + HOMEPAGE_URL "https://github.com/ROCm-Developer-Tools/rocprofiler-register-internal") + +# needed for modulefile and setup-env.sh +string(REPLACE "-" "_" PROJECT_NAME_UNDERSCORED "${PROJECT_NAME}") + +find_package(Git) + +if(Git_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --tags + OUTPUT_VARIABLE ROCPROFILER_REGISTER_GIT_DESCRIBE + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _GIT_DESCRIBE_RESULT + ERROR_QUIET) + + if(NOT _GIT_DESCRIBE_RESULT EQUAL 0) + execute_process( + COMMAND ${GIT_EXECUTABLE} describe + OUTPUT_VARIABLE ROCPROFILER_REGISTER_GIT_DESCRIBE + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _GIT_DESCRIBE_RESULT + ERROR_QUIET) + endif() + + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse HEAD + OUTPUT_VARIABLE ROCPROFILER_REGISTER_GIT_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +else() + set(ROCPROFILER_REGISTER_GIT_DESCRIBE "v${ROCPROFILER_REGISTER_VERSION}") + set(ROCPROFILER_REGISTER_GIT_REVISION "") +endif() + +message( + STATUS + "[${PROJECT_NAME}] version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} (${FULL_VERSION_STRING})" + ) +message(STATUS "[${PROJECT_NAME}] git revision: ${ROCPROFILER_REGISTER_GIT_REVISION}") +message(STATUS "[${PROJECT_NAME}] git describe: ${ROCPROFILER_REGISTER_GIT_DESCRIBE}") +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${PROJECT_SOURCE_DIR}/cmake/Modules + ${CMAKE_MODULE_PATH}) + +include(GNUInstallDirs) # install directories + +include(rocprofiler_register_utilities) # various functions/macros +include(rocprofiler_register_interfaces) # interface libraries +include(rocprofiler_register_compilers) # compiler identification +include(rocprofiler_register_options) # project options +include(rocprofiler_register_build_settings) # build flags +include(rocprofiler_register_formatting) # formatting +include(rocprofiler_register_linting) # clang-tidy +include(rocprofiler_register_config_interfaces) # configure interface libraries + +set(CMAKE_C_VISIBILITY_PRESET "hidden") +set(CMAKE_CXX_VISIBILITY_PRESET "hidden") +set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") + +enable_testing() +include(CTest) + +add_subdirectory(source) + +if(ROCPROFILER_REGISTER_BUILD_TESTS) + add_subdirectory(tests) +endif() + +if(ROCPROFILER_REGISTER_BUILD_SAMPLES) + add_subdirectory(samples) +endif() + +# +include(rocprofiler_register_config_install) +include(rocprofiler_register_config_packaging) + +rocprofiler_register_print_features() diff --git a/VERSION b/VERSION new file mode 100644 index 0000000000..6e8bf73aa5 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/cmake/Templates/modulefile.in b/cmake/Templates/modulefile.in new file mode 100644 index 0000000000..4b335a160e --- /dev/null +++ b/cmake/Templates/modulefile.in @@ -0,0 +1,16 @@ +#%Module1.0 + +module-whatis "@PROJECT_NAME_UNDERSCORED@ (version @PROJECT_VERSION@)" + +proc ModulesHelp { } { +puts stderr "Loads @PROJECT_NAME_UNDERSCORED@ v@PROJECT_VERSION@" +} + +set ROOT [file normalize [file dirname [file normalize ${ModulesCurrentModulefile}]]/../../..] + +setenv @PROJECT_NAME_UNDERSCORED@_ROOT "${ROOT}" +prepend-path CMAKE_PREFIX_PATH "${ROOT}" +prepend-path PATH "${ROOT}/bin" +prepend-path LD_LIBRARY_PATH "${ROOT}/@CMAKE_INSTALL_LIBDIR@" +prepend-path PYTHONPATH "${ROOT}/@CMAKE_INSTALL_PYTHONDIR@" +setenv @PROJECT_NAME_UNDERSCORED@_DIR "${ROOT}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME_UNDERSCORED@" diff --git a/cmake/Templates/rocprofiler-register-config.cmake.in b/cmake/Templates/rocprofiler-register-config.cmake.in new file mode 100644 index 0000000000..db66aafc06 --- /dev/null +++ b/cmake/Templates/rocprofiler-register-config.cmake.in @@ -0,0 +1,32 @@ +# - Config file for @PROJECT_NAME@ and its component libraries +# It defines the following variables: +# +# @PROJECT_NAME@_INCLUDE_DIRS +# @PROJECT_NAME@_LIBRARIES +# @PROJECT_NAME@_INTERNAL_DEFINES - used by the test suite + +# compute paths +get_filename_component(@PROJECT_NAME@_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +# version +include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-version.cmake) + +@PACKAGE_INIT@ + +set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") +set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@") +get_filename_component(@PROJECT_NAME@_ROOT_DIR ${@PROJECT_NAME@_INCLUDE_DIR} PATH) + +include("${@PROJECT_NAME@_CMAKE_DIR}/@PROJECT_NAME@-library-targets.cmake") + +if(TARGET @PROJECT_NAME@::@PROJECT_NAME@) + set(@PROJECT_NAME@_LIBRARIES @PROJECT_NAME@::@PROJECT_NAME@) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + @PROJECT_NAME@ + FOUND_VAR @PROJECT_NAME@_FOUND + REQUIRED_VARS @PROJECT_NAME@_ROOT_DIR @PROJECT_NAME@_INCLUDE_DIR @PROJECT_NAME@_LIBRARIES + VERSION_VAR @PROJECT_NAME@_VERSION + HANDLE_COMPONENTS) diff --git a/cmake/Templates/setup-env.sh.in b/cmake/Templates/setup-env.sh.in new file mode 100644 index 0000000000..b6e449a582 --- /dev/null +++ b/cmake/Templates/setup-env.sh.in @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +BASEDIR=$(dirname ${BASH_SOURCE[0]}) +command -v realpath &> /dev/null && BASEDIR=$(realpath ${BASEDIR}/../..) || BASEDIR=$(cd ${BASEDIR}/../.. && pwd) + +if [ ! -d "${BASEDIR}" ]; then + echo "${BASEDIR} does not exist" + return 1 +fi + +@PROJECT_NAME_UNDERSCORED@_ROOT=${BASEDIR} +PATH=${BASEDIR}/bin:${PATH} +LD_LIBRARY_PATH=${BASEDIR}/@CMAKE_INSTALL_LIBDIR@:${LD_LIBRARY_PATH} +PYTHONPATH=${BASEDIR}/@CMAKE_INSTALL_PYTHONDIR@:${PYTHONPATH} +CMAKE_PREFIX_PATH=${BASEDIR}:${CMAKE_PREFIX_PATH} +@PROJECT_NAME_UNDERSCORED@_DIR=${BASEDIR}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME_UNDERSCORED@ + +export @PROJECT_NAME_UNDERSCORED@_ROOT +export PATH +export LD_LIBRARY_PATH +export PYTHONPATH +export CMAKE_PREFIX_PATH +export @PROJECT_NAME_UNDERSCORED@_DIR diff --git a/cmake/rocprofiler_register_build_settings.cmake b/cmake/rocprofiler_register_build_settings.cmake new file mode 100644 index 0000000000..1d37776157 --- /dev/null +++ b/cmake/rocprofiler_register_build_settings.cmake @@ -0,0 +1,107 @@ +# ######################################################################################## +# +# Handles the build settings +# +# ######################################################################################## + +include_guard(DIRECTORY) + +include(GNUInstallDirs) +include(FindPackageHandleStandardArgs) +include(rocprofiler_register_compilers) +include(rocprofiler_register_utilities) + +target_compile_definitions(rocprofiler-register-build-flags + INTERFACE $<$:DEBUG>) + +if(ROCPROFILER_REGISTER_BUILD_CI) + rocprofiler_register_target_compile_definitions(rocprofiler-register-build-flags + INTERFACE ROCPROFILER_REGISTER_CI) +endif() + +# ----------------------------------------------------------------------------------------# +# dynamic linking and runtime libraries +# +if(CMAKE_DL_LIBS AND NOT "${CMAKE_DL_LIBS}" STREQUAL "dl") + # if cmake provides dl library, use that + set(dl_LIBRARY + ${CMAKE_DL_LIBS} + CACHE FILEPATH "dynamic linking system library") +endif() + +foreach(_TYPE dl rt) + if(NOT ${_TYPE}_LIBRARY) + find_library(${_TYPE}_LIBRARY NAMES ${_TYPE}) + find_package_handle_standard_args(${_TYPE}-library REQUIRED_VARS ${_TYPE}_LIBRARY) + if(${_TYPE}-library_FOUND) + string(TOUPPER "${_TYPE}" _TYPE_UC) + rocprofiler_register_target_compile_definitions( + rocprofiler-register-${_TYPE} + INTERFACE ROCPROFILER_REGISTER_${_TYPE_UC}=1) + target_link_libraries(rocprofiler-register-${_TYPE} + INTERFACE ${${_TYPE}_LIBRARY}) + if("${_TYPE}" STREQUAL "dl" AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) + # This instructs the linker to add all symbols, not only used ones, to the + # dynamic symbol table. This option is needed for some uses of dlopen or + # to allow obtaining backtraces from within a program. + rocprofiler_register_target_compile_options( + rocprofiler-register-${_TYPE} + LANGUAGES C CXX + LINK_LANGUAGES C CXX + INTERFACE "-rdynamic") + endif() + else() + rocprofiler_register_target_compile_definitions( + rocprofiler-register-${_TYPE} + INTERFACE ROCPROFILER_REGISTER_${_TYPE_UC}=0) + endif() + endif() +endforeach() + +target_link_libraries(rocprofiler-register-build-flags INTERFACE rocprofiler-register::dl) + +# ----------------------------------------------------------------------------------------# +# set the compiler flags +# +rocprofiler_register_target_compile_options( + rocprofiler-register-build-flags + INTERFACE "-W" "-Wall" "-Wno-unknown-pragmas" "-fstack-protector-strong" + "-Wstack-protector") + +# ----------------------------------------------------------------------------------------# +# debug-safe optimizations +# +rocprofiler_register_target_compile_options( + rocprofiler-register-build-flags + LANGUAGES CXX + INTERFACE "-faligned-new") + +# ----------------------------------------------------------------------------------------# +# developer build flags +# +rocprofiler_register_target_compile_options( + rocprofiler-register-developer-flags + LANGUAGES C CXX + INTERFACE "-Werror" "-Wdouble-promotion" "-Wshadow" "-Wextra") + +if(NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) + rocprofiler_register_target_compile_options( + rocprofiler-register-developer-flags + LANGUAGES C CXX + INTERFACE "-Wstack-usage=524288" # 512 KB + ) +endif() + +if(ROCPROFILER_REGISTER_BUILD_DEVELOPER) + target_link_libraries(rocprofiler-register-build-flags + INTERFACE rocprofiler-register::developer-flags) +endif() + +# ----------------------------------------------------------------------------------------# +# user customization +# +get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + +if(NOT APPLE OR "$ENV{CONDA_PYTHON_EXE}" STREQUAL "") + rocprofiler_register_target_user_flags(rocprofiler-register-build-flags "CXX") +endif() diff --git a/cmake/rocprofiler_register_compilers.cmake b/cmake/rocprofiler_register_compilers.cmake new file mode 100644 index 0000000000..f3c3fb7414 --- /dev/null +++ b/cmake/rocprofiler_register_compilers.cmake @@ -0,0 +1,352 @@ +# include guard +# ######################################################################################## +# +# Compilers +# +# ######################################################################################## +# +# sets (cached): +# +# CMAKE_C_COMPILER_IS_ CMAKE_CXX_COMPILER_IS_ +# +# where TYPE is: - GNU - CLANG - INTEL - INTEL_ICC - INTEL_ICPC - PGI - XLC - HP_ACC - +# MIPS - MSVC +# + +include(CheckCCompilerFlag) +include(CheckCSourceCompiles) +include(CheckCSourceRuns) + +include(CheckCXXCompilerFlag) +include(CheckCXXSourceCompiles) +include(CheckCXXSourceRuns) + +include(CMakeParseArguments) + +include(rocprofiler_register_utilities) + +# ----------------------------------------------------------------------------------------# +# macro converting string to list +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_REGISTER_TO_LIST _VAR _STR) + string(REPLACE " " " " ${_VAR} "${_STR}") + string(REPLACE " " ";" ${_VAR} "${_STR}") +endmacro() + +# ----------------------------------------------------------------------------------------# +# macro converting string to list +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_REGISTER_TO_STRING _VAR _STR) + string(REPLACE ";" " " ${_VAR} "${_STR}") +endmacro() + +# ----------------------------------------------------------------------------------------# +# Macro to add to string +# ----------------------------------------------------------------------------------------# +macro(add _VAR _FLAG) + if(NOT "${_FLAG}" STREQUAL "") + if("${${_VAR}}" STREQUAL "") + set(${_VAR} "${_FLAG}") + else() + set(${_VAR} "${${_VAR}} ${_FLAG}") + endif() + endif() +endmacro() + +# ----------------------------------------------------------------------------------------# +# call before running check_{c,cxx}_compiler_flag +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_REGISTER_BEGIN_FLAG_CHECK) + if(ROCPROFILER_REGISTER_QUIET_CONFIG) + if(NOT DEFINED CMAKE_REQUIRED_QUIET) + set(CMAKE_REQUIRED_QUIET OFF) + endif() + rocprofiler_register_save_variables(FLAG_CHECK VARIABLES CMAKE_REQUIRED_QUIET) + set(CMAKE_REQUIRED_QUIET ON) + endif() +endmacro() + +# ----------------------------------------------------------------------------------------# +# call after running check_{c,cxx}_compiler_flag +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_REGISTER_END_FLAG_CHECK) + if(ROCPROFILER_REGISTER_QUIET_CONFIG) + rocprofiler_register_restore_variables(FLAG_CHECK VARIABLES CMAKE_REQUIRED_QUIET) + endif() +endmacro() + +# ----------------------------------------------------------------------------------------# +# check flag +# ----------------------------------------------------------------------------------------# +function(ROCPROFILER_REGISTER_TARGET_COMPILE_OPTIONS _TARG_TARGET) + cmake_parse_arguments(_TARG "BUILD_INTERFACE;FORCE" "" + "PUBLIC;INTERFACE;PRIVATE;LANGUAGES;LINK_LANGUAGES" ${ARGN}) + + if(NOT _TARG_MODE) + set(_TARG_MODE INTERFACE) + endif() + + get_property(_ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + set(_SUPPORTED_LANGUAGES "C" "CXX") + + if(NOT _TARG_LANGUAGES) + foreach(_LANG ${_ENABLED_LANGUAGES}) + if(_LANG IN_LIST _SUPPORTED_LANGUAGES) + list(APPEND _TARG_LANGUAGES ${_LANG}) + endif() + endforeach() + endif() + + string(TOLOWER "_${_TARG_TARGET}" _TARG_TARGET_LC) + + function(rocprofiler_register_target_compile_option_impl _TARGET_IMPL + _TARGET_MODE_IMPL _TARGET_LANG_IMPL _TARGET_FLAG_IMPL) + if(_TARG_BUILD_INTERFACE) + target_compile_options( + ${_TARGET_IMPL} + ${_TARGET_MODE_IMPL} + $:${_TARGET_FLAG_IMPL}>> + ) + else() + target_compile_options( + ${_TARGET_IMPL} ${_TARGET_MODE_IMPL} + $<$:${_TARGET_FLAG_IMPL}>) + endif() + + if("${_TARGET_LANG_IMPL}" IN_LIST _TARG_LINK_LANGUAGES) + if(_TARG_BUILD_INTERFACE) + target_link_options( + ${_TARGET_IMPL} + ${_TARGET_MODE_IMPL} + $:${_TARGET_FLAG_IMPL}>> + ) + else() + target_link_options( + ${_TARGET_IMPL} ${_TARGET_MODE_IMPL} + $<$:${_TARGET_FLAG_IMPL}>) + endif() + endif() + endfunction() + + function(rocprofiler_register_target_compile_option_patch_name _P_LANG _P_IN _P_OUT) + string(TOLOWER "${_P_LANG}" _P_LANG) + string(REGEX REPLACE "^(/|-)" "${_P_LANG}${_TARG_TARGET_LC}_" _NAME "${_P_IN}") + string(REPLACE "-" "_" _NAME "${_NAME}") + string(REPLACE " " "_" _NAME "${_NAME}") + string(REPLACE "=" "_" _NAME "${_NAME}") + set(${_P_OUT} + "${_NAME}" + PARENT_SCOPE) + endfunction() + + if(NOT DEFINED rocprofiler_register_c_error AND NOT DEFINED + rocprofiler_register_cxx_error) + rocprofiler_register_begin_flag_check() + check_c_compiler_flag("-Werror" c_rocprofiler_register_werror) + check_cxx_compiler_flag("-Werror" cxx_rocprofiler_register_werror) + rocprofiler_register_end_flag_check() + endif() + + foreach(_TARG_MODE PUBLIC INTERFACE PRIVATE) + foreach(_FLAG ${_TARG_${_TARG_MODE}}) + foreach(_LANG ${_TARG_LANGUAGES}) + unset(FLAG_NAME) + rocprofiler_register_target_compile_option_patch_name(${_LANG} "${_FLAG}" + FLAG_NAME) + + if(_TARG_FORCE) + set(${FLAG_NAME} + 1 + CACHE INTERNAL "${_LANG} flag: ${_FLAG}") + else() + rocprofiler_register_begin_flag_check() + + if("${_LANG}" STREQUAL "C") + if(c_rocprofiler_register_werror) + check_c_compiler_flag("${_FLAG} -Werror" ${FLAG_NAME}) + else() + check_c_compiler_flag("${_FLAG}" ${FLAG_NAME}) + endif() + elseif("${_LANG}" STREQUAL "CXX") + if(cxx_rocprofiler_register_werror) + check_cxx_compiler_flag("${_FLAG} -Werror" ${FLAG_NAME}) + else() + check_cxx_compiler_flag("${_FLAG}" ${FLAG_NAME}) + endif() + else() + message( + FATAL_ERROR + "rocprofiler_register_target_compile_option :: unknown language: ${_LANG}" + ) + endif() + + rocprofiler_register_end_flag_check() + endif() + + if(${FLAG_NAME}) + rocprofiler_register_target_compile_option_impl( + ${_TARG_TARGET} ${_TARG_MODE} ${_LANG} "${_FLAG}") + endif() + endforeach() + endforeach() + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# add to any language +# ----------------------------------------------------------------------------------------# +function(ROCPROFILER_REGISTER_TARGET_USER_FLAGS _TARGET _LANGUAGE) + + set(_FLAGS ${${_LANGUAGE}FLAGS} $ENV{${_LANGUAGE}FLAGS} ${${_LANGUAGE}_FLAGS} + $ENV{${_LANGUAGE}_FLAGS}) + + string(REPLACE " " ";" _FLAGS "${_FLAGS}") + + set(${PROJECT_NAME}_${_LANGUAGE}_FLAGS + ${${PROJECT_NAME}_${_LANGUAGE}_FLAGS} ${_FLAGS} + PARENT_SCOPE) + + set(${PROJECT_NAME}_${_LANGUAGE}_COMPILE_OPTIONS + ${${PROJECT_NAME}_${_LANGUAGE}_COMPILE_OPTIONS} ${_FLAGS} + PARENT_SCOPE) + + target_compile_options(${_TARGET} + INTERFACE $<$:${_FLAGS}>) +endfunction() + +# ----------------------------------------------------------------------------------------# +# add compiler definition +# ----------------------------------------------------------------------------------------# +function(ROCPROFILER_REGISTER_TARGET_COMPILE_DEFINITIONS _TARG _VIS) + foreach(_DEF ${ARGN}) + if(NOT "${_DEF}" MATCHES "[A-Za-z_]+=.*" AND "${_DEF}" MATCHES + "^ROCPROFILER_REGISTER_") + set(_DEF "${_DEF}=1") + endif() + target_compile_definitions(${_TARG} ${_VIS} $<$:${_DEF}>) + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# determine compiler types for each language +# ----------------------------------------------------------------------------------------# +get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(LANG C CXX HIP CUDA) + + if(NOT DEFINED CMAKE_${LANG}_COMPILER) + set(CMAKE_${LANG}_COMPILER "") + endif() + + if(NOT DEFINED CMAKE_${LANG}_COMPILER_ID) + set(CMAKE_${LANG}_COMPILER_ID "") + endif() + + function(SET_COMPILER_VAR VAR _BOOL) + set(CMAKE_${LANG}_COMPILER_IS_${VAR} + ${_BOOL} + CACHE INTERNAL "CMake ${LANG} compiler identification (${VAR})" FORCE) + mark_as_advanced(CMAKE_${LANG}_COMPILER_IS_${VAR}) + endfunction() + + if(("${LANG}" STREQUAL "C" AND CMAKE_COMPILER_IS_GNUCC) + OR ("${LANG}" STREQUAL "CXX" AND CMAKE_COMPILER_IS_GNUCXX)) + + # GNU compiler + set_compiler_var(GNU 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "icc.*") + + # Intel icc compiler + set_compiler_var(INTEL 1) + set_compiler_var(INTEL_ICC 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "icpc.*") + + # Intel icpc compiler + set_compiler_var(INTEL 1) + set_compiler_var(INTEL_ICPC 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "AppleClang") + + # Clang/LLVM compiler + set_compiler_var(CLANG 1) + set_compiler_var(APPLE_CLANG 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "Clang") + + # Clang/LLVM compiler + set_compiler_var(CLANG 1) + + # HIP Clang compiler + if(CMAKE_${LANG}_COMPILER MATCHES "hipcc") + set_compiler_var(HIPCC 1) + endif() + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "PGI") + + # PGI compiler + set_compiler_var(PGI 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "xlC" AND UNIX) + + # IBM xlC compiler + set_compiler_var(XLC 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "aCC" AND UNIX) + + # HP aC++ compiler + set_compiler_var(HP_ACC 1) + + elseif( + CMAKE_${LANG}_COMPILER MATCHES "CC" + AND CMAKE_SYSTEM_NAME MATCHES "IRIX" + AND UNIX) + + # IRIX MIPSpro CC Compiler + set_compiler_var(MIPS 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "Intel") + + set_compiler_var(INTEL 1) + + set(CTYPE ICC) + if("${LANG}" STREQUAL "CXX") + set(CTYPE ICPC) + endif() + + set_compiler_var(INTEL_${CTYPE} 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "MSVC") + + # Windows Visual Studio compiler + set_compiler_var(MSVC 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "NVIDIA") + + # NVCC + set_compiler_var(NVIDIA 1) + + endif() + + # set other to no + foreach( + TYPE + GNU + INTEL + INTEL_ICC + INTEL_ICPC + APPLE_CLANG + CLANG + PGI + XLC + HP_ACC + MIPS + MSVC + NVIDIA + HIPCC) + if(NOT DEFINED CMAKE_${LANG}_COMPILER_IS_${TYPE}) + set_compiler_var(${TYPE} 0) + endif() + endforeach() + +endforeach() diff --git a/cmake/rocprofiler_register_config_install.cmake b/cmake/rocprofiler_register_config_install.cmake new file mode 100644 index 0000000000..afa4e64c9a --- /dev/null +++ b/cmake/rocprofiler_register_config_install.cmake @@ -0,0 +1,87 @@ +# include guard +include_guard(GLOBAL) + +include(CMakePackageConfigHelpers) + +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME config) + +install( + EXPORT rocprofiler-register-library-targets + FILE rocprofiler-register-library-targets.cmake + NAMESPACE rocprofiler-register:: + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register) + +configure_file( + ${PROJECT_SOURCE_DIR}/cmake/Templates/setup-env.sh.in + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/setup-env.sh @ONLY) + +configure_file( + ${PROJECT_SOURCE_DIR}/cmake/Templates/modulefile.in + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/modulefiles/${PROJECT_NAME}/${PROJECT_VERSION} + @ONLY) + +install( + FILES ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/setup-env.sh + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME} + COMPONENT setup) + +install( + FILES + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/modulefiles/${PROJECT_NAME}/${PROJECT_VERSION} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/modulefiles/${PROJECT_NAME} + COMPONENT setup) + +# ------------------------------------------------------------------------------# +# install tree +# +set(PROJECT_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}) +set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) + +configure_package_config_file( + ${PROJECT_SOURCE_DIR}/cmake/Templates/${PROJECT_NAME}-config.cmake.in + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register + INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} + PATH_VARS PROJECT_INSTALL_DIR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR) + +write_basic_package_version_file( + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMinorVersion) + +install( + FILES + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} + OPTIONAL) + +export(PACKAGE ${PROJECT_NAME}) + +# ------------------------------------------------------------------------------# +# build tree +# +set(_BUILDTREE_EXPORT_DIR + "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register") + +if(NOT EXISTS "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") + file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +endif() + +if(NOT EXISTS "${_BUILDTREE_EXPORT_DIR}") + file(MAKE_DIRECTORY "${_BUILDTREE_EXPORT_DIR}") +endif() + +if(NOT EXISTS "${_BUILDTREE_EXPORT_DIR}/rocprofiler-register-library-targets.cmake") + file(TOUCH "${_BUILDTREE_EXPORT_DIR}/rocprofiler-register-library-targets.cmake") +endif() + +export( + EXPORT rocprofiler-register-library-targets + NAMESPACE rocprofiler-register:: + FILE "${_BUILDTREE_EXPORT_DIR}/rocprofiler-register-library-targets.cmake") + +set(rocprofiler_register_DIR + "${_BUILDTREE_EXPORT_DIR}" + CACHE PATH "rocprofiler-register" FORCE) diff --git a/cmake/rocprofiler_register_config_interfaces.cmake b/cmake/rocprofiler_register_config_interfaces.cmake new file mode 100644 index 0000000000..5f7a2e1e72 --- /dev/null +++ b/cmake/rocprofiler_register_config_interfaces.cmake @@ -0,0 +1,67 @@ +# include guard +include_guard(DIRECTORY) + +# ######################################################################################## +# +# External Packages are found here +# +# ######################################################################################## + +target_include_directories( + rocprofiler-register-headers + INTERFACE $ + $ + $ + $) + +# ensure the env overrides the appending /opt/rocm later +string(REPLACE ":" ";" CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH};${CMAKE_PREFIX_PATH}") + +# ----------------------------------------------------------------------------------------# +# +# Threading +# +# ----------------------------------------------------------------------------------------# + +set(CMAKE_THREAD_PREFER_PTHREAD ON) +set(THREADS_PREFER_PTHREAD_FLAG OFF) + +find_package(Threads ${rocprofiler_register_FIND_QUIETLY} + ${rocprofiler_register_FIND_REQUIREMENT}) +if(Threads_FOUND) + target_link_libraries(rocprofiler-register-threading + INTERFACE $) +endif() + +# ----------------------------------------------------------------------------------------# +# +# dynamic linking (dl) and runtime (rt) libraries +# +# ----------------------------------------------------------------------------------------# + +foreach(_LIB dl rt) + find_library(${_LIB}_LIBRARY NAMES ${_LIB}) + find_package_handle_standard_args(${_LIB}-library REQUIRED_VARS ${_LIB}_LIBRARY) + if(${_LIB}_LIBRARY) + target_link_libraries( + rocprofiler-register-${_LIB} INTERFACE $ + $) + endif() +endforeach() + +# ----------------------------------------------------------------------------------------# +# +# stdc++fs (filesystem) library +# +# ----------------------------------------------------------------------------------------# + +find_library(stdcxxfs_LIBRARY NAMES stdc++fs) +find_package_handle_standard_args(stdcxxfs-library REQUIRED_VARS stdcxxfs_LIBRARY) + +if(stdcxxfs_LIBRARY) + target_link_libraries(rocprofiler-register-stdcxxfs + INTERFACE $) +else() + target_link_libraries(rocprofiler-register-stdcxxfs + INTERFACE $) +endif() diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake new file mode 100644 index 0000000000..4e13119443 --- /dev/null +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -0,0 +1,100 @@ +# configure packaging + +# Add packaging directives +set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) +set(CPACK_PACKAGE_VENDOR "Advanced Micro Devices, Inc.") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}") +set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") +set(CPACK_PACKAGE_CONTACT "jonathan.madsen@amd.com") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) +set(ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME + "${CMAKE_SYSTEM_NAME}" + CACHE STRING "System name, e.g. Linux or -") +set(ROCPROFILER_REGISTER_CPACK_PACKAGE_SUFFIX + "" + CACHE STRING "Package suffix") + +set(CPACK_PACKAGE_FILE_NAME + "${CPACK_PACKAGE_NAME}-${ROCPROFILER_REGISTER_VERSION}-${ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME}${ROCPROFILER_REGISTER_CPACK_PACKAGE_SUFFIX}" + ) +if(DEFINED ENV{CPACK_PACKAGE_FILE_NAME}) + set(CPACK_PACKAGE_FILE_NAME $ENV{CPACK_PACKAGE_FILE_NAME}) +endif() + +set(ROCPROFILER_REGISTER_PACKAGE_FILE_NAME + ${CPACK_PACKAGE_NAME}-${ROCPROFILER_REGISTER_VERSION}-${ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME}${ROCPROFILER_REGISTER_CPACK_PACKAGE_SUFFIX} + ) +rocprofiler_register_add_feature(ROCPROFILER_REGISTER_PACKAGE_FILE_NAME "CPack filename") + +# -------------------------------------------------------------------------------------- # +# +# Debian package specific variables +# +# -------------------------------------------------------------------------------------- # + +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE_URL}") +set(CPACK_DEBIAN_PACKAGE_RELEASE + "${ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME}${ROCPROFILER_REGISTER_CPACK_PACKAGE_SUFFIX}" + ) +string(REGEX REPLACE "([a-zA-Z])-([0-9])" "\\1\\2" CPACK_DEBIAN_PACKAGE_RELEASE + "${CPACK_DEBIAN_PACKAGE_RELEASE}") +string(REPLACE "-" "~" CPACK_DEBIAN_PACKAGE_RELEASE "${CPACK_DEBIAN_PACKAGE_RELEASE}") +if(DEFINED ENV{CPACK_DEBIAN_PACKAGE_RELEASE}) + set(CPACK_DEBIAN_PACKAGE_RELEASE $ENV{CPACK_DEBIAN_PACKAGE_RELEASE}) +endif() + +set(_DEBIAN_PACKAGE_DEPENDS "") +if(rocm_version_FOUND) + set(_ROCPROFILER_REGISTER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})") + set(_ROCTRACER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})") + set(_ROCM_SMI_SUFFIX + " (>= ${rocm_version_MAJOR_VERSION}.0.0.${rocm_version_NUMERIC_VERSION})") +endif() +string(REPLACE ";" ", " _DEBIAN_PACKAGE_DEPENDS "${_DEBIAN_PACKAGE_DEPENDS}") +set(CPACK_DEBIAN_PACKAGE_DEPENDS + "${_DEBIAN_PACKAGE_DEPENDS}" + CACHE STRING "Debian package dependencies" FORCE) +rocprofiler_register_add_feature(CPACK_DEBIAN_PACKAGE_DEPENDS + "Debian package dependencies") +set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") + +# -------------------------------------------------------------------------------------- # +# +# RPM package specific variables +# +# -------------------------------------------------------------------------------------- # + +if(DEFINED CPACK_PACKAGING_INSTALL_PREFIX) + set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}") +endif() + +set(CPACK_RPM_PACKAGE_RELEASE + "${ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME}${ROCPROFILER_REGISTER_CPACK_PACKAGE_SUFFIX}" + ) +string(REGEX REPLACE "([a-zA-Z])-([0-9])" "\\1\\2" CPACK_RPM_PACKAGE_RELEASE + "${CPACK_RPM_PACKAGE_RELEASE}") +string(REPLACE "-" "~" CPACK_RPM_PACKAGE_RELEASE "${CPACK_RPM_PACKAGE_RELEASE}") +if(DEFINED ENV{CPACK_RPM_PACKAGE_RELEASE}) + set(CPACK_RPM_PACKAGE_RELEASE $ENV{CPACK_RPM_PACKAGE_RELEASE}) +endif() + +# Get rpm distro +if(CPACK_RPM_PACKAGE_RELEASE) + set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) +endif() +set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") + +# -------------------------------------------------------------------------------------- # +# +# Prepare final version for the CPACK use +# +# -------------------------------------------------------------------------------------- # + +set(CPACK_PACKAGE_VERSION + "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}" + ) + +include(CPack) diff --git a/cmake/rocprofiler_register_formatting.cmake b/cmake/rocprofiler_register_formatting.cmake new file mode 100644 index 0000000000..ffc23f0243 --- /dev/null +++ b/cmake/rocprofiler_register_formatting.cmake @@ -0,0 +1,104 @@ +# ------------------------------------------------------------------------------# +# +# creates following targets to format code: +# - format +# - format-source +# - format-cmake +# - format-python +# - format-rocprofiler-register-source +# - format-rocprofiler-register-cmake +# - format-rocprofiler-register-python +# +# ------------------------------------------------------------------------------# + +include_guard(DIRECTORY) + +find_program(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE NAMES clang-format-11 + clang-format-mp-11) +find_program(ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE NAMES cmake-format) +find_program(ROCPROFILER_REGISTER_BLACK_FORMAT_EXE NAMES black) + +add_custom_target(format-rocprofiler-register) +if(NOT TARGET format) + add_custom_target(format) +endif() +foreach(_TYPE source python cmake) + if(NOT TARGET format-${_TYPE}) + add_custom_target(format-${_TYPE}) + endif() +endforeach() + +if(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE + OR ROCPROFILER_REGISTER_BLACK_FORMAT_EXE + OR ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE) + + set(rocp_source_files) + set(rocp_header_files) + set(rocp_python_files) + set(rocp_cmake_files ${PROJECT_SOURCE_DIR}/CMakeLists.txt) + + foreach(_DIR cmake samples source tests) + foreach(_TYPE header_files source_files cmake_files python_files) + set(${_TYPE}) + endforeach() + file(GLOB_RECURSE header_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.h + ${PROJECT_SOURCE_DIR}/${_DIR}/*.hpp) + file(GLOB_RECURSE source_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.c + ${PROJECT_SOURCE_DIR}/${_DIR}/*.cpp) + file(GLOB_RECURSE cmake_files ${PROJECT_SOURCE_DIR}/${_DIR}/*CMakeLists.txt + ${PROJECT_SOURCE_DIR}/${_DIR}/*.cmake) + file(GLOB_RECURSE python_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.py) + foreach(_TYPE header_files source_files cmake_files python_files) + list(APPEND rocp_${_TYPE} ${${_TYPE}}) + endforeach() + endforeach() + + foreach(_TYPE header_files source_files cmake_files python_files) + if(rocp_${_TYPE}) + list(REMOVE_DUPLICATES rocp_${_TYPE}) + list(SORT rocp_${_TYPE}) + endif() + endforeach() + + if(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE AND (rocp_source_files OR rocp_header_files)) + add_custom_target( + format-rocprofiler-register-source + ${ROCPROFILER_REGISTER_CLANG_FORMAT_EXE} -i ${rocp_header_files} + ${rocp_source_files} + COMMENT + "[rocprofiler-register] Running source formatter ${ROCPROFILER_REGISTER_CLANG_FORMAT_EXE}..." + ) + endif() + + if(ROCPROFILER_REGISTER_BLACK_FORMAT_EXE AND rocp_python_files) + add_custom_target( + format-rocprofiler-register-python + ${ROCPROFILER_REGISTER_BLACK_FORMAT_EXE} -q ${rocp_python_files} + COMMENT + "[rocprofiler-register] Running Python formatter ${ROCPROFILER_REGISTER_BLACK_FORMAT_EXE}..." + ) + endif() + + if(ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE AND rocp_cmake_files) + add_custom_target( + format-rocprofiler-register-cmake + ${ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE} -i ${rocp_cmake_files} + COMMENT + "[rocprofiler-register] Running CMake formatter ${ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE}..." + ) + endif() + + foreach(_TYPE source python cmake) + if(TARGET format-rocprofiler-register-${_TYPE}) + add_dependencies(format-rocprofiler-register + format-rocprofiler-register-${_TYPE}) + add_dependencies(format-${_TYPE} format-rocprofiler-register-${_TYPE}) + endif() + endforeach() + + foreach(_TYPE source python) + if(TARGET format-rocprofiler-register-${_TYPE}) + add_dependencies(format format-rocprofiler-register-${_TYPE}) + endif() + endforeach() +endif() diff --git a/cmake/rocprofiler_register_interfaces.cmake b/cmake/rocprofiler_register_interfaces.cmake new file mode 100644 index 0000000000..9bac2556dd --- /dev/null +++ b/cmake/rocprofiler_register_interfaces.cmake @@ -0,0 +1,34 @@ +# +# +# Forward declaration of all INTERFACE targets +# +# + +include(rocprofiler_register_utilities) + +# +# interfaces for build flags +# +rocprofiler_register_add_interface_library( + rocprofiler-register-headers + "Provides minimal set of include flags to compile with rocprofiler-register") +rocprofiler_register_add_interface_library( + rocprofiler-register-build-flags + "Provides generalized build flags for rocprofiler-register" INTERNAL) +rocprofiler_register_add_interface_library(rocprofiler-register-threading + "Enables multithreading support" INTERNAL) +rocprofiler_register_add_interface_library( + rocprofiler-register-developer-flags + "Compiler flags for developers (more warnings, etc.)" INTERNAL) +rocprofiler_register_add_interface_library(rocprofiler-register-memcheck "Sanitizer" + INTERNAL) + +# +# interfaces for libraries +# +rocprofiler_register_add_interface_library( + rocprofiler-register-dl "Build flags for dynamic linking library" INTERNAL) +rocprofiler_register_add_interface_library(rocprofiler-register-rt + "Build flags for runtime library" INTERNAL) +rocprofiler_register_add_interface_library(rocprofiler-register-stdcxxfs + "C++ filesystem library" INTERNAL) diff --git a/cmake/rocprofiler_register_linting.cmake b/cmake/rocprofiler_register_linting.cmake new file mode 100644 index 0000000000..1a34218e6f --- /dev/null +++ b/cmake/rocprofiler_register_linting.cmake @@ -0,0 +1,47 @@ +include_guard(GLOBAL) + +# ----------------------------------------------------------------------------------------# +# +# Clang Tidy +# +# ----------------------------------------------------------------------------------------# + +find_program( + ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND + NAMES clang-tidy-18 + clang-tidy-17 + clang-tidy-16 + clang-tidy-15 + clang-tidy-14 + clang-tidy-13 + clang-tidy-12 + clang-tidy-11 + clang-tidy) + +macro(ROCPROFILER_REGISTER_ACTIVATE_CLANG_TIDY) + if(ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) + if(NOT ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND) + message( + FATAL_ERROR + "ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY is ON but clang-tidy is not found!" + ) + endif() + + set(CMAKE_CXX_CLANG_TIDY ${ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND} + -header-filter=${PROJECT_SOURCE_DIR}/.*) + + # Create a preprocessor definition that depends on .clang-tidy content so the + # compile command will change when .clang-tidy changes. This ensures that a + # subsequent build re-runs clang-tidy on all sources even if they do not otherwise + # need to be recompiled. Nothing actually uses this definition. We add it to + # targets on which we run clang-tidy just to get the build dependency on the + # .clang-tidy file. + file(SHA1 ${PROJECT_SOURCE_DIR}/.clang-tidy clang_tidy_sha1) + set(CLANG_TIDY_DEFINITIONS "CLANG_TIDY_SHA1=${clang_tidy_sha1}") + unset(clang_tidy_sha1) + endif() +endmacro() + +macro(ROCPROFILER_REGISTER_DEACTIVATE_CLANG_TIDY) + set(CMAKE_CXX_CLANG_TIDY) +endmacro() diff --git a/cmake/rocprofiler_register_memcheck.cmake b/cmake/rocprofiler_register_memcheck.cmake new file mode 100644 index 0000000000..de096c6389 --- /dev/null +++ b/cmake/rocprofiler_register_memcheck.cmake @@ -0,0 +1,40 @@ +# +# +# +set(ROCPROFILER_REGISTER_MEMCHECK_TYPES "ThreadSanitizer" "AddressSanitizer" + "LeakSanitizer" "UndefinedBehaviorSanitizer") + +if(ROCPROFILER_REGISTER_MEMCHECK AND NOT ROCPROFILER_REGISTER_MEMCHECK IN_LIST + ROCPROFILER_REGISTER_MEMCHECK_TYPES) + message( + FATAL_ERROR + "Unsupported memcheck type '${ROCPROFILER_REGISTER_MEMCHECK}'. Options: ${ROCPROFILER_REGISTER_MEMCHECK_TYPES}" + ) +endif() + +set_property(CACHE ROCPROFILER_REGISTER_MEMCHECK + PROPERTY STRINGS "${ROCPROFILER_REGISTER_MEMCHECK_TYPES}") + +function(rocprofiler_register_add_memcheck_flags _TYPE _LIB) + target_compile_options( + rocprofiler-register-memcheck + INTERFACE $ + -static-lib${_LIB}) + target_link_options( + rocprofiler-register-memcheck INTERFACE $) +endfunction() + +# always unset so that it doesn't preload if memcheck disabled +unset(ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV CACHE) + +if(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "AddressSanitizer") + rocprofiler_register_add_memcheck_flags("address" "asan") +elseif(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "LeakSanitizer") + rocprofiler_register_add_memcheck_flags("leak" "lsan") +elseif(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "ThreadSanitizer") + rocprofiler_register_add_memcheck_flags("thread" "tsan") +elseif(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "UndefinedBehaviorSanitizer") + rocprofiler_register_add_memcheck_flags("undefined" "ubsan") +endif() diff --git a/cmake/rocprofiler_register_options.cmake b/cmake/rocprofiler_register_options.cmake new file mode 100644 index 0000000000..e25debc4ae --- /dev/null +++ b/cmake/rocprofiler_register_options.cmake @@ -0,0 +1,90 @@ +# +# rocprofiler_register_options.cmake +# +# Configure miscellaneous settings +# +# standard cmake options +rocprofiler_register_add_option(BUILD_SHARED_LIBS "Build shared libraries" ON) +rocprofiler_register_add_option(BUILD_STATIC_LIBS "Build static libraries" OFF) +rocprofiler_register_add_option(CMAKE_POSITION_INDEPENDENT_CODE + "Build position independent code" ON) + +# export compile commands in the project +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_EXTENSIONS OFF) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_TESTS + "Enable building the tests" OFF) +rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_SAMPLES "Enable building the + code samples" OFF) +rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_CI + "Enable continuous integration additions" OFF ADVANCED) +rocprofiler_register_add_option(ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY + "Enable clang-tidy checks" OFF ADVANCED) +rocprofiler_register_add_option( + ROCPROFILER_REGISTER_BUILD_DEVELOPER "Extra build flags for development like -Werror" + ${ROCPROFILER_REGISTER_BUILD_CI} ADVANCED) + +# In the future, we will do this even with clang-tidy enabled +if(ROCPROFILER_REGISTER_BUILD_CI AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) + message( + STATUS + "Forcing ROCPROFILER_REGISTER_BUILD_DEVELOPER=ON because ROCPROFILER_REGISTER_BUILD_CI=ON" + ) + set(ROCPROFILER_REGISTER_BUILD_DEVELOPER + ON + CACHE + BOOL + "Any compiler warnings are errors (forced due ROCPROFILER_REGISTER_BUILD_CI=ON)" + FORCE) +endif() + +set(ROCPROFILER_REGISTER_BUILD_TYPES "Release" "RelWithDebInfo" "Debug" "MinSizeRel" + "Coverage") + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE + "Release" + CACHE STRING "Build type" FORCE) +endif() + +if(NOT CMAKE_BUILD_TYPE IN_LIST ROCPROFILER_REGISTER_BUILD_TYPES) + message( + FATAL_ERROR + "Unsupported build type '${CMAKE_BUILD_TYPE}'. Options: ${ROCPROFILER_REGISTER_BUILD_TYPES}" + ) +endif() + +if(ROCPROFILER_REGISTER_BUILD_CI) + foreach(_BUILD_TYPE ${ROCPROFILER_REGISTER_BUILD_TYPES}) + string(TOUPPER "${_BUILD_TYPE}" _BUILD_TYPE) + + # remove NDEBUG preprocessor def so that asserts are triggered + string(REGEX REPLACE ".DNDEBUG" "" CMAKE_C_FLAGS_${_BUILD_TYPE} + "${CMAKE_C_FLAGS_${_BUILD_TYPE}}") + string(REGEX REPLACE ".DNDEBUG" "" CMAKE_CXX_FLAGS_${_BUILD_TYPE} + "${CMAKE_CXX_FLAGS_${_BUILD_TYPE}}") + endforeach() +endif() + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "${ROCPROFILER_REGISTER_BUILD_TYPES}") +endif() + +rocprofiler_register_add_cache_option(ROCPROFILER_REGISTER_MEMCHECK "" STRING + "Memory checker type" ADVANCED) + +# ASAN is defined by testing team on Jenkins +if(ASAN) + set(ROCPROFILER_REGISTER_MEMCHECK + "AddressSanitizer" + CACHE STRING "Memory checker type (forced by ASAN defined)" FORCE) +endif() + +include(rocprofiler_register_memcheck) diff --git a/cmake/rocprofiler_register_utilities.cmake b/cmake/rocprofiler_register_utilities.cmake new file mode 100644 index 0000000000..3ba52d49fc --- /dev/null +++ b/cmake/rocprofiler_register_utilities.cmake @@ -0,0 +1,941 @@ +# include guard +include_guard(GLOBAL) + +# MacroUtilities - useful macros and functions for generic tasks +# + +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) +cmake_policy(SET CMP0057 NEW) + +include(CMakeDependentOption) +include(CMakeParseArguments) + +# ----------------------------------------------------------------------- +# message which handles ROCPROFILER_REGISTER_QUIET_CONFIG settings +# ----------------------------------------------------------------------- +# +function(ROCPROFILER_REGISTER_MESSAGE TYPE) + if(NOT ROCPROFILER_REGISTER_QUIET_CONFIG) + message(${TYPE} "[rocprofiler-register] ${ARGN}") + endif() +endfunction() + +# ----------------------------------------------------------------------- +# Save a set of variables with the given prefix +# ----------------------------------------------------------------------- +macro(ROCPROFILER_REGISTER_SAVE_VARIABLES _PREFIX) + # parse args + cmake_parse_arguments( + SAVE + "" # options + "CONDITION" # single value args + "VARIABLES" # multiple value args + ${ARGN}) + if(DEFINED SAVE_CONDITION AND NOT "${SAVE_CONDITION}" STREQUAL "") + if(${SAVE_CONDITION}) + foreach(_VAR ${SAVE_VARIABLES}) + if(DEFINED ${_VAR}) + set(${_PREFIX}_${_VAR} "${${_VAR}}") + else() + message(AUTHOR_WARNING "${_VAR} is not defined") + endif() + endforeach() + endif() + else() + foreach(_VAR ${SAVE_VARIABLES}) + if(DEFINED ${_VAR}) + set(${_PREFIX}_${_VAR} "${${_VAR}}") + else() + message(AUTHOR_WARNING "${_VAR} is not defined") + endif() + endforeach() + endif() + unset(SAVE_CONDITION) + unset(SAVE_VARIABLES) +endmacro() + +# ----------------------------------------------------------------------- +# Restore a set of variables with the given prefix +# ----------------------------------------------------------------------- +macro(ROCPROFILER_REGISTER_RESTORE_VARIABLES _PREFIX) + # parse args + cmake_parse_arguments( + RESTORE + "" # options + "CONDITION" # single value args + "VARIABLES" # multiple value args + ${ARGN}) + if(DEFINED RESTORE_CONDITION AND NOT "${RESTORE_CONDITION}" STREQUAL "") + if(${RESTORE_CONDITION}) + foreach(_VAR ${RESTORE_VARIABLES}) + if(DEFINED ${_PREFIX}_${_VAR}) + set(${_VAR} ${${_PREFIX}_${_VAR}}) + unset(${_PREFIX}_${_VAR}) + else() + message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined") + endif() + endforeach() + endif() + else() + foreach(_VAR ${RESTORE_VARIABLES}) + if(DEFINED ${_PREFIX}_${_VAR}) + set(${_VAR} ${${_PREFIX}_${_VAR}}) + unset(${_PREFIX}_${_VAR}) + else() + message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined") + endif() + endforeach() + endif() + unset(RESTORE_CONDITION) + unset(RESTORE_VARIABLES) +endmacro() + +# ----------------------------------------------------------------------- +# function - rocprofiler_register_capitalize - make a string capitalized (first letter is +# capital) usage: capitalize("SHARED" CShared) message(STATUS "-- CShared is +# \"${CShared}\"") $ -- CShared is "Shared" +function(ROCPROFILER_REGISTER_CAPITALIZE str var) + # make string lower + string(TOLOWER "${str}" str) + string(SUBSTRING "${str}" 0 1 _first) + string(TOUPPER "${_first}" _first) + string(SUBSTRING "${str}" 1 -1 _remainder) + string(CONCAT str "${_first}" "${_remainder}") + set(${var} + "${str}" + PARENT_SCOPE) +endfunction() + +# ------------------------------------------------------------------------------# +# function rocprofiler_register_strip_target( [FORCE] [EXPLICIT]) +# +# Creates a post-build command which strips a binary. FORCE flag will override +# +function(ROCPROFILER_REGISTER_STRIP_TARGET) + cmake_parse_arguments(STRIP "FORCE;EXPLICIT" "" "ARGS" ${ARGN}) + + list(LENGTH STRIP_UNPARSED_ARGUMENTS NUM_UNPARSED) + + if(NUM_UNPARSED EQUAL 1) + set(_TARGET "${STRIP_UNPARSED_ARGUMENTS}") + else() + rocprofiler_register_message( + FATAL_ERROR + "rocprofiler_register_strip_target cannot deduce target from \"${ARGN}\"") + endif() + + if(NOT TARGET "${_TARGET}") + rocprofiler_register_message( + FATAL_ERROR + "rocprofiler_register_strip_target not provided valid target: \"${_TARGET}\"") + endif() + + if(CMAKE_STRIP AND (STRIP_FORCE OR ROCPROFILER_REGISTER_STRIP_LIBRARIES)) + if(STRIP_EXPLICIT) + add_custom_command( + TARGET ${_TARGET} + POST_BUILD + COMMAND ${CMAKE_STRIP} ${STRIP_ARGS} $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Stripping ${_TARGET}...") + else() + add_custom_command( + TARGET ${_TARGET} + POST_BUILD + COMMAND + ${CMAKE_STRIP} -w --keep-symbol="rocprofiler_register_init" + --keep-symbol="rocprofiler_register_finalize" + --keep-symbol="rocprofiler_register_push_trace" + --keep-symbol="rocprofiler_register_pop_trace" + --keep-symbol="rocprofiler_register_push_region" + --keep-symbol="rocprofiler_register_pop_region" + --keep-symbol="rocprofiler_register_set_env" + --keep-symbol="rocprofiler_register_set_mpi" + --keep-symbol="rocprofiler_register_reset_preload" + --keep-symbol="rocprofiler_register_set_instrumented" + --keep-symbol="rocprofiler_register_user_*" + --keep-symbol="ompt_start_tool" --keep-symbol="kokkosp_*" + --keep-symbol="OnLoad" --keep-symbol="OnUnload" + --keep-symbol="OnLoadToolProp" --keep-symbol="OnUnloadTool" + --keep-symbol="__libc_start_main" ${STRIP_ARGS} + $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Stripping ${_TARGET}...") + endif() + endif() +endfunction() + +# ------------------------------------------------------------------------------# +# function add_rocprofiler_register_test_target() +# +# Creates a target which runs ctest but depends on all the tests being built. +# +function(ADD_ROCPROFILER_REGISTER_TEST_TARGET) + if(NOT TARGET rocprofiler-register-test) + add_custom_target( + rocprofiler-register-test + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target test + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMENT "Running tests...") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# macro rocprofiler_register_checkout_git_submodule() +# +# Run "git submodule update" if a file in a submodule does not exist +# +# ARGS: RECURSIVE (option) -- add "--recursive" flag RELATIVE_PATH (one value) -- +# typically the relative path to submodule from PROJECT_SOURCE_DIR WORKING_DIRECTORY (one +# value) -- (default: PROJECT_SOURCE_DIR) TEST_FILE (one value) -- file to check for +# (default: CMakeLists.txt) ADDITIONAL_CMDS (many value) -- any addition commands to pass +# +function(ROCPROFILER_REGISTER_CHECKOUT_GIT_SUBMODULE) + # parse args + cmake_parse_arguments( + CHECKOUT "RECURSIVE" + "RELATIVE_PATH;WORKING_DIRECTORY;TEST_FILE;REPO_URL;REPO_BRANCH" + "ADDITIONAL_CMDS" ${ARGN}) + + if(NOT CHECKOUT_WORKING_DIRECTORY) + set(CHECKOUT_WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + endif() + + if(NOT CHECKOUT_TEST_FILE) + set(CHECKOUT_TEST_FILE "CMakeLists.txt") + endif() + + # default assumption + if(NOT CHECKOUT_REPO_BRANCH) + set(CHECKOUT_REPO_BRANCH "master") + endif() + + find_package(Git) + set(_DIR "${CHECKOUT_WORKING_DIRECTORY}/${CHECKOUT_RELATIVE_PATH}") + # ensure the (possibly empty) directory exists + if(NOT EXISTS "${_DIR}") + if(NOT CHECKOUT_REPO_URL) + message(FATAL_ERROR "submodule directory does not exist") + endif() + endif() + + # if this file exists --> project has been checked out if not exists --> not been + # checked out + set(_TEST_FILE "${_DIR}/${CHECKOUT_TEST_FILE}") + # assuming a .gitmodules file exists + set(_SUBMODULE "${PROJECT_SOURCE_DIR}/.gitmodules") + + set(_TEST_FILE_EXISTS OFF) + if(EXISTS "${_TEST_FILE}" AND NOT IS_DIRECTORY "${_TEST_FILE}") + set(_TEST_FILE_EXISTS ON) + endif() + + if(_TEST_FILE_EXISTS) + return() + endif() + + find_package(Git REQUIRED) + + set(_SUBMODULE_EXISTS OFF) + if(EXISTS "${_SUBMODULE}" AND NOT IS_DIRECTORY "${_SUBMODULE}") + set(_SUBMODULE_EXISTS ON) + endif() + + set(_HAS_REPO_URL OFF) + if(NOT "${CHECKOUT_REPO_URL}" STREQUAL "") + set(_HAS_REPO_URL ON) + endif() + + # if the module has not been checked out + if(NOT _TEST_FILE_EXISTS AND _SUBMODULE_EXISTS) + # perform the checkout + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH} + WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY} + RESULT_VARIABLE RET) + + # check the return code + if(RET GREATER 0) + set(_CMD "${GIT_EXECUTABLE} submodule update --init ${_RECURSE} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH}") + message( + STATUS "function(rocprofiler_register_checkout_git_submodule) failed.") + message(FATAL_ERROR "Command: \"${_CMD}\"") + else() + set(_TEST_FILE_EXISTS ON) + endif() + endif() + + if(NOT _TEST_FILE_EXISTS AND _HAS_REPO_URL) + message( + STATUS "Checking out '${CHECKOUT_REPO_URL}' @ '${CHECKOUT_REPO_BRANCH}'...") + + # remove the existing directory + if(EXISTS "${_DIR}") + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${_DIR}) + endif() + + # perform the checkout + execute_process( + COMMAND + ${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH} + WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY} + RESULT_VARIABLE RET) + + # perform the submodule update + if(CHECKOUT_RECURSIVE + AND EXISTS "${_DIR}" + AND IS_DIRECTORY "${_DIR}") + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE} + WORKING_DIRECTORY ${_DIR} + RESULT_VARIABLE RET) + endif() + + # check the return code + if(RET GREATER 0) + set(_CMD + "${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH}" + ) + message( + STATUS "function(rocprofiler_register_checkout_git_submodule) failed.") + message(FATAL_ERROR "Command: \"${_CMD}\"") + else() + set(_TEST_FILE_EXISTS ON) + endif() + endif() + + if(NOT EXISTS "${_TEST_FILE}" OR NOT _TEST_FILE_EXISTS) + message( + FATAL_ERROR + "Error checking out submodule: '${CHECKOUT_RELATIVE_PATH}' to '${_DIR}'") + endif() + +endfunction() + +# ----------------------------------------------------------------------------------------# +# try to find a package quietly +# +function(ROCPROFILER_REGISTER_TEST_FIND_PACKAGE PACKAGE_NAME OUTPUT_VAR) + cmake_parse_arguments(PACKAGE "" "" "UNSET" ${ARGN}) + find_package(${PACKAGE_NAME} QUIET ${PACKAGE_UNPARSED_ARGUMENTS}) + if(NOT ${PACKAGE_NAME}_FOUND) + set(${OUTPUT_VAR} + OFF + PARENT_SCOPE) + else() + set(${OUTPUT_VAR} + ON + PARENT_SCOPE) + endif() + foreach(_ARG ${PACKAGE_UNSET} FIND_PACKAGE_MESSAGE_DETAILS_${PACKAGE_NAME}) + unset(${_ARG} CACHE) + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# macro to add an interface lib +# +function(ROCPROFILER_REGISTER_ADD_INTERFACE_LIBRARY _TARGET _DESCRIPT) + add_library(${_TARGET} INTERFACE) + string(REPLACE "${PROJECT_NAME}-" "" _ALIAS_TARGET "${_TARGET}") + add_library(${PROJECT_NAME}::${_ALIAS_TARGET} ALIAS ${_TARGET}) + add_library(${PROJECT_NAME}::${_TARGET} ALIAS ${_TARGET}) + set(_ARGS "${ARGN}") + if(NOT "INTERNAL" IN_LIST _ARGS) + install( + TARGETS ${_TARGET} + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT core + EXPORT ${PROJECT_NAME}-library-targets + OPTIONAL) + endif() +endfunction() + +# ----------------------------------------------------------------------- +# function add_feature( ) Add a project feature, whose activation is +# specified by the existence of the variable , to the list of enabled/disabled +# features, plus a docstring describing the feature +# +function(ROCPROFILER_REGISTER_ADD_FEATURE _var _description) + set(EXTRA_DESC "") + foreach(currentArg ${ARGN}) + if(NOT "${currentArg}" STREQUAL "${_var}" + AND NOT "${currentArg}" STREQUAL "${_description}" + AND NOT "${currentArg}" STREQUAL "CMAKE_DEFINE" + AND NOT "${currentArg}" STREQUAL "DOC") + set(EXTRA_DESC "${EXTA_DESC}${currentArg}") + endif() + endforeach() + + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_FEATURES ${_var}) + set_property(GLOBAL PROPERTY ${_var}_DESCRIPTION "${_description}${EXTRA_DESC}") + + if("CMAKE_DEFINE" IN_LIST ARGN) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES + "${_var} @${_var}@") + if(ROCPROFILER_REGISTER_BUILD_DOCS) + set_property( + GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_var}` | ${_description}${EXTRA_DESC} |") + endif() + elseif("DOC" IN_LIST ARGN AND ROCPROFILER_REGISTER_BUILD_DOCS) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_var}` | ${_description}${EXTRA_DESC} |") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function add_option( [NO_FEATURE]) Add an +# option and add as a feature if NO_FEATURE is not provided +# +function(ROCPROFILER_REGISTER_ADD_OPTION _NAME _MESSAGE _DEFAULT) + option(${_NAME} "${_MESSAGE}" ${_DEFAULT}) + if("NO_FEATURE" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + else() + rocprofiler_register_add_feature(${_NAME} "${_MESSAGE}") + if(ROCPROFILER_REGISTER_BUILD_DOCS) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_NAME}` | ${_MESSAGE} |") + endif() + endif() + if("ADVANCED" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + endif() + if("CMAKE_DEFINE" IN_LIST ARGN) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME}) + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function rocprofiler_register_add_cache_option( +# [NO_FEATURE] [ADVANCED] [CMAKE_DEFINE]) +# +function(ROCPROFILER_REGISTER_ADD_CACHE_OPTION _NAME _DEFAULT _TYPE _MESSAGE) + set(_FORCE) + if("FORCE" IN_LIST ARGN) + set(_FORCE FORCE) + endif() + + set(${_NAME} + "${_DEFAULT}" + CACHE ${_TYPE} "${_MESSAGE}" ${_FORCE}) + + if("NO_FEATURE" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + else() + rocprofiler_register_add_feature(${_NAME} "${_MESSAGE}") + + if(ROCPROFILER_REGISTER_BUILD_DOCS) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_NAME}` | ${_MESSAGE} |") + endif() + endif() + + if("ADVANCED" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + endif() + + if("CMAKE_DEFINE" IN_LIST ARGN) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME}) + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function rocprofiler_register_report_feature_changes() :: print changes in features +# +function(ROCPROFILER_REGISTER_REPORT_FEATURE_CHANGES) + get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES) + if(NOT "${_features}" STREQUAL "") + list(REMOVE_DUPLICATES _features) + list(SORT _features) + endif() + foreach(_feature ${_features}) + if("${ARGN}" STREQUAL "") + rocprofiler_register_watch_for_change(${_feature}) + elseif("${_feature}" IN_LIST ARGN) + rocprofiler_register_watch_for_change(${_feature}) + endif() + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function print_enabled_features() Print enabled features plus their docstrings. +# +function(ROCPROFILER_REGISTER_PRINT_ENABLED_FEATURES) + set(_basemsg "The following features are defined/enabled (+):") + set(_currentFeatureText "${_basemsg}") + get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES) + if(NOT "${_features}" STREQUAL "") + list(REMOVE_DUPLICATES _features) + list(SORT _features) + endif() + foreach(_feature ${_features}) + if(${_feature}) + # add feature to text + set(_currentFeatureText "${_currentFeatureText}\n ${_feature}") + # get description + get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION) + # print description, if not standard ON/OFF, print what is set to + if(_desc) + if(NOT "${${_feature}}" STREQUAL "ON" AND NOT "${${_feature}}" STREQUAL + "TRUE") + set(_currentFeatureText + "${_currentFeatureText}: ${_desc} -- [\"${${_feature}}\"]") + else() + string(REGEX REPLACE "^${PROJECT_NAME}_USE_" "" _feature_tmp + "${_feature}") + string(TOLOWER "${_feature_tmp}" _feature_tmp_l) + rocprofiler_register_capitalize("${_feature_tmp}" _feature_tmp_c) + foreach(_var _feature _feature_tmp _feature_tmp_l _feature_tmp_c) + set(_ver "${${${_var}}_VERSION}") + if(NOT "${_ver}" STREQUAL "") + set(_desc "${_desc} -- [found version ${_ver}]") + break() + endif() + unset(_ver) + endforeach() + set(_currentFeatureText "${_currentFeatureText}: ${_desc}") + endif() + set(_desc NOTFOUND) + endif() + endif() + endforeach() + + if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}") + message(STATUS "${_currentFeatureText}\n") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function print_disabled_features() Print disabled features plus their docstrings. +# +function(ROCPROFILER_REGISTER_PRINT_DISABLED_FEATURES) + set(_basemsg "The following features are NOT defined/enabled (-):") + set(_currentFeatureText "${_basemsg}") + get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES) + if(NOT "${_features}" STREQUAL "") + list(REMOVE_DUPLICATES _features) + list(SORT _features) + endif() + foreach(_feature ${_features}) + if(NOT ${_feature}) + set(_currentFeatureText "${_currentFeatureText}\n ${_feature}") + + get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION) + + if(_desc) + set(_currentFeatureText "${_currentFeatureText}: ${_desc}") + set(_desc NOTFOUND) + endif(_desc) + endif() + endforeach(_feature) + + if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}") + message(STATUS "${_currentFeatureText}\n") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function print_features() Print all features plus their docstrings. +# +function(ROCPROFILER_REGISTER_PRINT_FEATURES) + rocprofiler_register_report_feature_changes() + rocprofiler_register_print_enabled_features() + rocprofiler_register_print_disabled_features() +endfunction() + +# ----------------------------------------------------------------------------------------# +# this function is provided to easily select which files use alternative compiler: +# +# GLOBAL --> all files TARGET --> all files in a target SOURCE --> specific +# source files DIRECTORY --> all files in directory PROJECT --> all files/targets in +# a project/subproject +# +function(rocprofiler_register_custom_compilation) + cmake_parse_arguments(COMP "GLOBAL;PROJECT" "COMPILER" "DIRECTORY;TARGET;SOURCE" + ${ARGN}) + + # find rocprofiler-register-launch-compiler + find_program( + ROCPROFILER_REGISTER_COMPILE_LAUNCHER + NAMES rocprofiler-register-launch-compiler + HINTS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} + PATHS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} + PATH_SUFFIXES scripts bin) + + if(NOT COMP_COMPILER) + message( + FATAL_ERROR + "rocprofiler_register_custom_compilation not provided COMPILER argument") + endif() + + if(NOT ROCPROFILER_REGISTER_COMPILE_LAUNCHER) + message( + FATAL_ERROR + "rocprofiler-register could not find 'rocprofiler-register-launch-compiler'. Please set '-DROCPROFILER_REGISTER_COMPILE_LAUNCHER=/path/to/launcher'" + ) + endif() + + if(COMP_GLOBAL) + # if global, don't bother setting others + set_property( + GLOBAL + PROPERTY + RULE_LAUNCH_COMPILE + "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" + ) + set_property( + GLOBAL + PROPERTY + RULE_LAUNCH_LINK + "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" + ) + else() + foreach(_TYPE PROJECT DIRECTORY TARGET SOURCE) + # make project/subproject scoping easy, e.g. + # rocprofiler_register_custom_compilation(PROJECT) after project(...) + if("${_TYPE}" STREQUAL "PROJECT" AND COMP_${_TYPE}) + list(APPEND COMP_DIRECTORY ${PROJECT_SOURCE_DIR}) + unset(COMP_${_TYPE}) + endif() + # set the properties if defined + if(COMP_${_TYPE}) + foreach(_VAL ${COMP_${_TYPE}}) + set_property( + ${_TYPE} ${_VAL} + PROPERTY + RULE_LAUNCH_COMPILE + "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" + ) + set_property( + ${_TYPE} ${_VAL} + PROPERTY + RULE_LAUNCH_LINK + "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" + ) + endforeach() + endif() + endforeach() + endif() +endfunction() + +function(ROCPROFILER_REGISTER_WATCH_FOR_CHANGE _var) + list(LENGTH ARGN _NUM_EXTRA_ARGS) + if(_NUM_EXTRA_ARGS EQUAL 1) + set(_VAR ${ARGN}) + else() + set(_VAR) + endif() + + macro(update_var _VAL) + if(_VAR) + set(${_VAR} + ${_VAL} + PARENT_SCOPE) + endif() + endmacro() + + update_var(OFF) + + set(_rocprofiler_register_watch_var_name ROCPROFILER_REGISTER_WATCH_VALUE_${_var}) + if(DEFINED ${_rocprofiler_register_watch_var_name}) + if("${${_var}}" STREQUAL "${${_rocprofiler_register_watch_var_name}}") + return() + else() + rocprofiler_register_message( + STATUS + "${_var} changed :: ${${_rocprofiler_register_watch_var_name}} --> ${${_var}}" + ) + update_var(ON) + endif() + else() + if(NOT "${${_var}}" STREQUAL "") + rocprofiler_register_message(STATUS "${_var} :: ${${_var}}") + update_var(ON) + endif() + endif() + + # store the value for the next run + set(${_rocprofiler_register_watch_var_name} + "${${_var}}" + CACHE INTERNAL "Last value of ${_var}" FORCE) +endfunction() + +function(ROCPROFILER_REGISTER_DIRECTORY) + cmake_parse_arguments(F "MKDIR;FAIL;FORCE" "PREFIX;OUTPUT_VARIABLE;WORKING_DIRECTORY" + "PATHS" ${ARGN}) + + if(F_PREFIX AND NOT IS_ABSOLUTE "${F_PREFIX}") + if(F_WORKING_DIRECTORY) + rocprofiler_register_message( + STATUS + "PREFIX was specified as a relative path, using working directory + prefix :: '${F_WORKING_DIRECTORY}/${F_PREFIX}'..." + ) + set(F_PREFIX ${F_WORKING_DIRECTORY}/${F_PREFIX}) + else() + rocprofiler_register_message( + FATAL_ERROR + "PREFIX was specified but it is not an absolute path: ${F_PREFIX}") + endif() + endif() + + if(NOT F_WORKING_DIRECTORY) + set(F_WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + endif() + + foreach(_PATH ${F_PREFIX} ${F_PATHS}) + if(F_PREFIX AND NOT "${_PATH}" STREQUAL "${F_PREFIX}") + # if path is relative, set to prefix + path + if(NOT IS_ABSOLUTE "${_PATH}") + set(_PATH ${F_PREFIX}/${_PATH}) + endif() + list(APPEND _OUTPUT_VAR ${_PATH}) + elseif(NOT F_PREFIX) + list(APPEND _OUTPUT_VAR ${_PATH}) + endif() + + if(NOT EXISTS "${_PATH}" AND F_FAIL) + rocprofiler_register_message(FATAL_ERROR + "Directory '${_PATH}' does not exist") + elseif(NOT IS_DIRECTORY "${_PATH}" AND F_FAIL) + rocprofiler_register_message(FATAL_ERROR + "'${_PATH}' exists but is not a directory") + elseif(NOT EXISTS "${_PATH}" AND F_MKDIR) + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH} + WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) + elseif( + EXISTS "${_PATH}" + AND NOT IS_DIRECTORY "${_PATH}" + AND F_MKDIR) + if(F_FORCE) + execute_process(COMMAND ${CMAKE_COMMAND} -E rm ${_PATH} + WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) + endif() + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH} + WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) + endif() + endforeach() + + if(F_OUTPUT_VARIABLE) + set(${F_OUTPUT_VARIABLE} + "${_OUTPUT_VAR}" + PARENT_SCOPE) + endif() +endfunction() + +function(ROCPROFILER_REGISTER_CHECK_PYTHON_DIRS_AND_VERSIONS) + cmake_parse_arguments(F "FAIL;UNSET" "RESULT_VARIABLE;OUTPUT_VARIABLE" "" ${ARGN}) + + list(LENGTH ROCPROFILER_REGISTER_PYTHON_VERSIONS _NUM_PYTHON_VERSIONS) + list(LENGTH ROCPROFILER_REGISTER_PYTHON_ROOT_DIRS _NUM_PYTHON_ROOT_DIRS) + + if(NOT _NUM_PYTHON_VERSIONS EQUAL _NUM_PYTHON_ROOT_DIRS) + set(_RET 1) + else() + set(_RET 0) + if(F_OUTPUT_VARIABLE) + set(${F_OUTPUT_VARIABLE} + ${_NUM_PYTHON_VERSIONS} + PARENT_SCOPE) + endif() + endif() + + if(F_RESULT_VARIABLE) + set(${F_RESULT_VARIABLE} + ${_RET} + PARENT_SCOPE) + endif() + + if(NOT ${_RET} EQUAL 0) + if(F_FAIL) + rocprofiler_register_message( + WARNING + "Error! Number of python versions : ${_NUM_PYTHON_VERSIONS}. VERSIONS :: ${ROCPROFILER_REGISTER_PYTHON_VERSIONS}" + ) + rocprofiler_register_message( + WARNING + "Error! Number of python root directories : ${_NUM_PYTHON_ROOT_DIRS}. ROOT DIRS :: ${ROCPROFILER_REGISTER_PYTHON_ROOT_DIRS}" + ) + rocprofiler_register_message( + FATAL_ERROR + "Error! Number of python versions != number of python root directories") + elseif(F_UNSET) + unset(ROCPROFILER_REGISTER_PYTHON_VERSIONS CACHE) + unset(ROCPROFILER_REGISTER_PYTHON_ROOT_DIRS CACHE) + if(F_OUTPUT_VARIABLE) + set(${F_OUTPUT_VARIABLE} 0) + endif() + endif() + endif() +endfunction() + +# ---------------------------------------------------------------------------- +# Console scripts +# +function(ROCPROFILER_REGISTER_PYTHON_CONSOLE_SCRIPT SCRIPT_NAME SCRIPT_SUBMODULE) + set(options) + set(args VERSION ROOT_DIR) + set(kwargs) + cmake_parse_arguments(ARG "${options}" "${args}" "${kwargs}" ${ARGN}) + + if(ARG_VERSION AND ARG_ROOT_DIR) + set(Python3_ROOT_DIR "${ARG_ROOT_DIR}") + find_package(Python3 ${ARG_VERSION} EXACT QUIET MODULE COMPONENTS Interpreter) + set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}") + configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in + ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} @ONLY) + + if(CMAKE_INSTALL_PYTHONDIR) + install( + PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT python + OPTIONAL) + endif() + + if(ROCPROFILER_REGISTER_BUILD_TESTING OR ROCPROFILER_REGISTER_BUILD_PYTHON) + add_test( + NAME ${SCRIPT_NAME}-console-script-test-${ARG_VERSION} + COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} --help + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + set_tests_properties( + ${SCRIPT_NAME}-console-script-test-${ARG_VERSION} + PROPERTIES LABELS "python;python-${ARG_VERSION};console-script") + add_test( + NAME ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION} + COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} --help + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + set_tests_properties( + ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION} + PROPERTIES ENVIRONMENT "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}" LABELS + "python;python-${ARG_VERSION};console-script") + endif() + else() + set(PYTHON_EXECUTABLE "python3") + + configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in + ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} @ONLY) + + if(CMAKE_INSTALL_PYTHONDIR) + install( + PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT python + OPTIONAL) + endif() + endif() +endfunction() + +function(ROCPROFILER_REGISTER_FIND_STATIC_LIBRARY) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + find_library(${ARGN}) +endfunction() + +function(ROCPROFILER_REGISTER_FIND_SHARED_LIBRARY) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + find_library(${ARGN}) +endfunction() + +function(ROCPROFILER_REGISTER_BUILDTREE_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR) + get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION) + get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION) + get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME) + set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) + set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) + + foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_TPL_SUFFIX}.${_TPL_VERSION}) + set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL}) + set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL}) + endforeach() + + string(REPLACE " " "-" _TAIL "${ARGN}") + + # build tree symbolic links + add_custom_target( + ${_NEW_NAME}-build-tree-library${_TAIL} ALL + ${CMAKE_COMMAND} -E create_symlink $ + ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION} + COMMAND + ${CMAKE_COMMAND} -E create_symlink + ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION} + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} + COMMAND + ${CMAKE_COMMAND} -E create_symlink + ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX} + WORKING_DIRECTORY ${_BUILD_TREE_DIR} + DEPENDS ${_TPL_TARGET} + COMMENT "Creating ${_NEW_NAME} from ${_TPL_TARGET}...") +endfunction() + +function(ROCPROFILER_REGISTER_INSTALL_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR + _COMPONENT) + get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION) + get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION) + get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME) + set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) + set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) + + foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_TPL_SUFFIX}.${_TPL_VERSION}) + set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL}) + set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL}) + endforeach() + + # build tree symbolic links + rocprofiler_register_buildtree_tpl("${_TPL_TARGET}" "${_NEW_NAME}" + "${_BUILD_TREE_DIR}" ${ARGN}) + + install( + FILES $ + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT ${_COMPONENT} + RENAME ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}) + + install( + FILES + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT ${_COMPONENT}) + +endfunction() + +function(COMPUTE_POW2_CEIL _OUTPUT _VALUE) + find_package(Python3 COMPONENTS Interpreter) + + if(Python3_FOUND) + execute_process( + COMMAND + ${Python3_EXECUTABLE} -c + "VALUE = ${_VALUE}; ispow2 = lambda x: x if (x and (not(x & (x - 1)))) else None; v = list(filter(ispow2, [x for x in range(VALUE, VALUE**2)])); print(v[0])" + RESULT_VARIABLE _POW2_RET + OUTPUT_VARIABLE _POW2_OUT + ERROR_VARIABLE _POW2_ERR + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(_POW2_RET EQUAL 0) + set(${_OUTPUT} + ${_POW2_OUT} + PARENT_SCOPE) + else() + set(${_OUTPUT} + "-1" + PARENT_SCOPE) + endif() + else() + set(${_OUTPUT} + "-1" + PARENT_SCOPE) + endif() + +endfunction() + +cmake_policy(POP) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..585d9d4c24 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ + +[tool.black] +line-length = 90 +target-version = ['py36', 'py37', 'py38', 'py39', 'py310'] +include = '\.py$' +exclude = ''' +( + /( + \.eggs + | \.git + | \.github + | \.tox + | \.venv + | \.misc + | \.vscode + | \.cache + | \.pytest_cache + | dist + | external + | build + | build-release + | build-rocprofiler + )/ +) +''' diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt new file mode 100644 index 0000000000..925feac8b6 --- /dev/null +++ b/samples/CMakeLists.txt @@ -0,0 +1,6 @@ +# +# Samples +# +project(rocprofiler-register-samples LANGUAGES C CXX) + +add_subdirectory(library-implementation) diff --git a/samples/library-implementation/CMakeLists.txt b/samples/library-implementation/CMakeLists.txt new file mode 100644 index 0000000000..bff53798e3 --- /dev/null +++ b/samples/library-implementation/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# +# +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) + +project(rocprofiler-register-library-implementation LANGUAGES C CXX) + +if("${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}") + find_package(rocprofiler-register REQUIRED) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_EXTENSIONS OFF) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + +add_library(rocp-reg-hip-demo SHARED) +target_sources(rocp-reg-hip-demo PRIVATE demo.cpp demo.hpp) +target_link_libraries(rocp-reg-hip-demo + PRIVATE rocprofiler-register::rocprofiler-register) diff --git a/samples/library-implementation/demo.cpp b/samples/library-implementation/demo.cpp new file mode 100644 index 0000000000..5a5243ac15 --- /dev/null +++ b/samples/library-implementation/demo.cpp @@ -0,0 +1,120 @@ +#include "demo.hpp" + +#include + +#include +#include +#include + +#define ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \ + HIP_VERSION_MAJOR, HIP_VERSION_MINOR, HIP_VERSION_PATCH) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(hip, ROCP_REG_VERSION) + +namespace hip +{ +namespace +{ +auto& +get_hip_api_table_impl() +{ + static auto _table = std::atomic{ nullptr }; + return _table; +} + +void +register_profiler_impl() +{ + static auto _const_api_table = HipApiTable{}; + initialize_hip_api_table(&_const_api_table); + + // set this before any recursive opportunity arises + get_hip_api_table_impl().exchange(&_const_api_table); + + // create a copy of the api table for modification by registration + static auto _profiler_api_table = HipApiTable{}; + copy_hip_api_table(&_profiler_api_table, &_const_api_table); + + void* _profiler_api_table_v = static_cast(&_profiler_api_table); + + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto success = + rocprofiler_register_library_api_table("hip", + &ROCPROFILER_REGISTER_IMPORT_FUNC(hip), + ROCP_REG_VERSION, + &_profiler_api_table_v, + 1, + &lib_id); + + if(success == 0) + { + auto* _api_table = &_const_api_table; + if(!get_hip_api_table_impl().compare_exchange_strong(_api_table, + &_profiler_api_table)) + { + // with the current impl, if we ever get here, someone is calling one the + // functions in this anonymous namespace that shouldn't + std::cerr + << "register_profiler_impl expected the API table to be the internal " + "implementation and yet it is not. something went wrong.\n"; + abort(); + } + } +} + +void +register_profiler() +{ + // this registration scheme is designed to minimize overhead once + // registered (only pay cost of checking atomic boolean) + // once the profiler is registered. If the library has not + // been registered and two or more threads try to register concurrently + // the first thread to acquire the lock below, will block the + // threads until registration is complete. However, + // if the same thread performing the registration re-enters this function + // i.e. this library's API is called during registration, this function + // will prevent a deadlock by not attempting to re-enter the + // the call-once and not releasing any waiting threads by flipping + // the _is_registered field to true. + static auto _is_registered = std::atomic{ false }; + + if(!_is_registered.load(std::memory_order_acquire)) + { + using mutex_t = std::recursive_mutex; + using auto_lock_t = std::unique_lock; + static auto _once = std::once_flag{}; + static auto _mutex = mutex_t{}; + + // defer the lock so we can check for recursion + auto _lk = auto_lock_t{ _mutex, std::defer_lock }; + + // this will be true if the same thread currently executing the call_once invokes + // the library's API while registering the profiler (e.g. tool which wants to + // instrument HIP API invokes a HIP function while registering with the profiler) + // we allow this thread to proceed and access the "const" API table but + // return so it does not flip _is_registered to true, which would result + // in any subsequent threads not waiting until the library is fully registered, + // resulting in missed callbacks for the tools + if(_lk.owns_lock()) return; + + // ensures any subsequent threads wait until the first thread + // finishes registration + _lk.lock(); + // call_once to ensure that we only register once + std::call_once(_once, register_profiler_impl); + // the first thread has completed registration and all + // threads waiting on lock will be released and this + // block will not be entered again + _is_registered.exchange(true, std::memory_order_release); + } +} +} // namespace + +HipApiTable* +get_hip_api_table() +{ + register_profiler(); + return get_hip_api_table_impl().load(std::memory_order_relaxed); +} +} // namespace hip diff --git a/samples/library-implementation/demo.hpp b/samples/library-implementation/demo.hpp new file mode 100644 index 0000000000..301068a408 --- /dev/null +++ b/samples/library-implementation/demo.hpp @@ -0,0 +1,37 @@ +#pragma once + +#define HIP_VERSION_MAJOR 1 +#define HIP_VERSION_MINOR 0 +#define HIP_VERSION_PATCH 0 + +#include + +extern "C" { +// fake hip function +void +hip_init(void); +} + +namespace hip +{ +struct HipApiTable +{ + uint64_t size = 0; + void (*functor)() = nullptr; +}; + +// populates hip api table with function pointers +inline void +initialize_hip_api_table(HipApiTable* dst) +{ + dst->size = sizeof(HipApiTable); + dst->functor = &hip_init; +} + +// copies the api table from src to dst +inline void +copy_hip_api_table(HipApiTable* dst, const HipApiTable* src) +{ + *dst = *src; +} +} // namespace hip diff --git a/scripts/address-sanitizer-suppr.txt b/scripts/address-sanitizer-suppr.txt new file mode 100644 index 0000000000..c094802b42 --- /dev/null +++ b/scripts/address-sanitizer-suppr.txt @@ -0,0 +1,3 @@ +# +# AddressSanitizer suppressions file for rocprofiler-register project. +# diff --git a/scripts/leak-sanitizer-suppr.txt b/scripts/leak-sanitizer-suppr.txt new file mode 100644 index 0000000000..e466c76ba2 --- /dev/null +++ b/scripts/leak-sanitizer-suppr.txt @@ -0,0 +1,3 @@ +# +# LeakSanitizer suppressions file for rocprofiler-register project. +# diff --git a/scripts/run-ci.py b/scripts/run-ci.py new file mode 100755 index 0000000000..f531a6c4c7 --- /dev/null +++ b/scripts/run-ci.py @@ -0,0 +1,463 @@ +#!/usr/bin/env python3 + + +import os +import re +import sys +import glob +import socket +import shutil +import argparse +import multiprocessing + +# this constant is used to define CTEST_PROJECT_NAME +# and default value for CTEST_SUBMIT_URL +_PROJECT_NAME = "rocprofiler-register" +_BASE_URL = "10.194.116.31/cdash" + + +def which(cmd, require): + v = shutil.which(cmd) + if require and v is None: + raise RuntimeError(f"{cmd} not found") + return v if v is not None else "" + + +def generate_custom(args, cmake_args, ctest_args): + if not os.path.exists(args.binary_dir): + os.makedirs(args.binary_dir) + + if args.memcheck is not None: + if args.coverage: + raise ValueError( + f"Enabling --memcheck={args.memcheck} and --coverage not supported" + ) + cmake_args += [f"-DROCPROFILER_REGISTER_MEMCHECK={args.memcheck}"] + + NAME = args.name + SITE = args.site + BUILD_JOBS = args.build_jobs + SUBMIT_URL = args.submit_url + SOURCE_DIR = os.path.realpath(args.source_dir) + BINARY_DIR = os.path.realpath(args.binary_dir) + CMAKE_ARGS = " ".join(cmake_args) + CTEST_ARGS = " ".join(ctest_args) + + GIT_CMD = which("git", require=True) + GCOV_CMD = which("gcov", require=False) + CMAKE_CMD = which("cmake", require=True) + # CTEST_CMD = which("ctest", require=True) + + NAME = re.sub(r"(.*)-([0-9]+)/merge", "PR_\\2_\\1", NAME) + + DEFAULT_CMAKE_ARGS = " ".join( + [f"-DROCPROFILER_REGISTER_BUILD_{x}=ON" for x in ["CI", "TESTS", "SAMPLES"]] + ) + + MEMCHECK_TYPE = "" if args.memcheck is None else args.memcheck + + MEMCHECK_SANITIZER_OPTIONS = "" + MEMCHECK_SUPPRESSION_FILE = "" + + if MEMCHECK_TYPE == "AddressSanitizer": + MEMCHECK_SANITIZER_OPTIONS = "detect_leaks=0 use_sigaltstack=0" + MEMCHECK_SUPPRESSION_FILE = f"{SOURCE_DIR}/scripts/address-sanitizer-suppr.txt" + elif MEMCHECK_TYPE == "LeakSanitizer": + MEMCHECK_SUPPRESSION_FILE = f"{SOURCE_DIR}/scripts/leak-sanitizer-suppr.txt" + elif MEMCHECK_TYPE == "ThreadSanitizer": + external_symbolizer_path = "" + for version in range(8, 20): + _symbolizer = shutil.which(f"llvm-symbolizer-{version}") + if _symbolizer: + external_symbolizer_path = f"external_symbolizer_path={_symbolizer}" + os.environ["TSAN_OPTIONS"] = " ".join( + [ + "history_size=5", + "second_deadlock_stack=1", + f"suppressions={SOURCE_DIR}/scripts/thread-sanitizer-suppr.txt", + external_symbolizer_path, + os.environ.get("TSAN_OPTIONS", ""), + ] + ) + + return f""" + set(CTEST_PROJECT_NAME "{_PROJECT_NAME}") + set(CTEST_NIGHTLY_START_TIME "05:00:00 UTC") + + set(CTEST_DROP_METHOD "http") + set(CTEST_DROP_SITE_CDASH TRUE) + set(CTEST_SUBMIT_URL "http://{SUBMIT_URL}") + + set(CTEST_UPDATE_TYPE git) + set(CTEST_UPDATE_VERSION_ONLY TRUE) + set(CTEST_GIT_COMMAND {GIT_CMD}) + set(CTEST_GIT_INIT_SUBMODULES FALSE) + + set(CTEST_OUTPUT_ON_FAILURE TRUE) + set(CTEST_USE_LAUNCHERS TRUE) + set(CMAKE_CTEST_ARGUMENTS --output-on-failure {CTEST_ARGS}) + + set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "100") + set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "100") + set(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE "51200") + set(CTEST_CUSTOM_COVERAGE_EXCLUDE "/usr/.*;/opt/.*;.*external/.*;.*samples/.*;.*tests/.*") + + set(CTEST_MEMORYCHECK_TYPE "{MEMCHECK_TYPE}") + set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "{MEMCHECK_SUPPRESSION_FILE}") + set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "{MEMCHECK_SANITIZER_OPTIONS}") + + set(CTEST_SITE "{SITE}") + set(CTEST_BUILD_NAME "{NAME}") + + set(CTEST_SOURCE_DIRECTORY {SOURCE_DIR}) + set(CTEST_BINARY_DIRECTORY {BINARY_DIR}) + + set(CTEST_CONFIGURE_COMMAND "{CMAKE_CMD} -B {BINARY_DIR} {SOURCE_DIR} {DEFAULT_CMAKE_ARGS} {CMAKE_ARGS}") + set(CTEST_BUILD_COMMAND "{CMAKE_CMD} --build {BINARY_DIR} --target all --parallel {BUILD_JOBS}") + set(CTEST_COVERAGE_COMMAND {GCOV_CMD}) + """ + + +def generate_dashboard_script(args): + CODECOV = 1 if args.coverage else 0 + DASHBOARD_MODE = args.mode + SOURCE_DIR = os.path.realpath(args.source_dir) + BINARY_DIR = os.path.realpath(args.binary_dir) + MEMCHECK = 1 if args.memcheck is not None else 0 + SUBMIT = 0 if args.disable_cdash else 1 + ARGN = "${ARGN}" + + if args.memcheck == "ThreadSanitizer": + MEMCHECK = 0 + + _script = f""" + macro(dashboard_submit) + if("{SUBMIT}" GREATER 0) + ctest_submit({ARGN}) + endif() + endmacro() + """ + + _script += """ + + include("${CMAKE_CURRENT_LIST_DIR}/CTestCustom.cmake") + + macro(handle_error _message _ret) + if(NOT ${${_ret}} EQUAL 0) + dashboard_submit(PARTS Done RETURN_VALUE _submit_ret) + message(FATAL_ERROR "${_message} failed: ${${_ret}}") + endif() + endmacro() + """ + + _script += f""" + ctest_start({DASHBOARD_MODE}) + ctest_update(SOURCE "{SOURCE_DIR}" RETURN_VALUE _update_ret + CAPTURE_CMAKE_ERROR _update_err) + ctest_configure(BUILD "{BINARY_DIR}" RETURN_VALUE _configure_ret) + dashboard_submit(PARTS Start Update Configure RETURN_VALUE _submit_ret) + + if(NOT _update_err EQUAL 0) + message(WARNING "ctest_update failed") + endif() + + handle_error("Configure" _configure_ret) + + ctest_build(BUILD "{BINARY_DIR}" RETURN_VALUE _build_ret) + dashboard_submit(PARTS Build RETURN_VALUE _submit_ret) + + handle_error("Build" _build_ret) + + if("{MEMCHECK}" GREATER 0) + ctest_memcheck(BUILD "{BINARY_DIR}" RETURN_VALUE _test_ret) + dashboard_submit(PARTS Test RETURN_VALUE _submit_ret) + else() + ctest_test(BUILD "{BINARY_DIR}" RETURN_VALUE _test_ret) + dashboard_submit(PARTS Test RETURN_VALUE _submit_ret) + endif() + + if("{CODECOV}" GREATER 0) + ctest_coverage( + BUILD "{BINARY_DIR}" + RETURN_VALUE _coverage_ret + CAPTURE_CMAKE_ERROR _coverage_err) + dashboard_submit(PARTS Coverage RETURN_VALUE _submit_ret) + endif() + + handle_error("Testing" _test_ret) + + dashboard_submit(PARTS Done RETURN_VALUE _submit_ret) + """ + return _script + + +def parse_cdash_args(args): + BUILD_JOBS = multiprocessing.cpu_count() + DASHBOARD_MODE = "Continuous" + DASHBOARD_STAGES = [ + "Start", + "Update", + "Configure", + "Build", + "Test", + "MemCheck", + "Coverage", + "Submit", + ] + SOURCE_DIR = os.getcwd() + BINARY_DIR = os.path.join(SOURCE_DIR, "build") + SITE = socket.gethostname() + SUBMIT_URL = f"{_BASE_URL}/submit.php?project={_PROJECT_NAME}" + + parser = argparse.ArgumentParser() + + parser.add_argument( + "-n", "--name", help="Job name", default=None, type=str, required=True + ) + parser.add_argument("-s", "--site", help="Site name", default=SITE, type=str) + parser.add_argument( + "-q", "--quiet", help="Disable printing logs", action="store_true" + ) + parser.add_argument( + "-c", "--coverage", help="Enable code coverage", action="store_true" + ) + parser.add_argument( + "-j", + "--build-jobs", + help="Number of build tasks", + default=BUILD_JOBS, + type=int, + ) + parser.add_argument( + "-B", + "--binary-dir", + help="Build directory", + default=BINARY_DIR, + type=str, + ) + parser.add_argument( + "-S", + "--source-dir", + help="Source directory", + default=SOURCE_DIR, + type=str, + ) + parser.add_argument( + "-F", + "--clean", + help="Remove existing build directory", + action="store_true", + ) + parser.add_argument( + "-M", + "--mode", + help="Dashboard mode", + default=DASHBOARD_MODE, + choices=("Continuous", "Nightly", "Experimental"), + type=str, + ) + parser.add_argument( + "-T", + "--stages", + help="Dashboard stages", + nargs="+", + default=DASHBOARD_STAGES, + choices=DASHBOARD_STAGES, + type=str, + ) + parser.add_argument( + "--submit-url", + help="CDash submission site", + default=SUBMIT_URL, + type=str, + ) + parser.add_argument( + "--repeat-until-pass", + help=" for --repeat until-pass:", + default=None, + type=int, + ) + parser.add_argument( + "--repeat-until-fail", + help=" for --repeat until-fail:", + default=None, + type=int, + ) + parser.add_argument( + "--repeat-after-timeout", + help=" for --repeat after-timeout:", + default=None, + type=int, + ) + parser.add_argument( + "--disable-cdash", + help="Disable submitting results to CDash dashboard", + action="store_true", + ) + parser.add_argument( + "--memcheck", + help="Run dynamic analysis tool", + default=None, + type=str, + choices=( + "ThreadSanitizer", + "AddressSanitizer", + "LeakSanitizer", + "UndefinedBehaviorSanitizer", + ), + ) + parser.add_argument( + "--linter", + help="Enable linting tool", + default=None, + type=str, + choices=("clang-tidy",), + ) + + return parser.parse_args(args) + + +def parse_args(args=None): + if args is None: + args = sys.argv[1:] + + index = 0 + input_args = [] + ctest_args = [] + cmake_args = [] + data = [input_args, cmake_args, ctest_args] + cmd = os.path.basename(sys.argv[0]) + + for itr in args: + if itr == "--": + index += 1 + if index > 2: + raise RuntimeError( + f"Usage: {cmd} -- -- " + ) + else: + data[index].append(itr) + + cdash_args = parse_cdash_args(input_args) + + if cdash_args.coverage: + cmake_args += ["-DROCPROFILER_REGISTER_BUILD_CODECOV=ON"] + + if cdash_args.linter == "clang-tidy": + cmake_args += ["-DROCPROFILER_REGISTER_ENABLE_CLANG_TIDY=ON"] + + def get_repeat_val(_param): + _value = getattr(cdash_args, f"repeat_{_param}".replace("-", "_")) + return [f"{_param}:{_value}"] if _value is not None and _value > 1 else [] + + repeat_args = ( + get_repeat_val("until-pass") + + get_repeat_val("until-fail") + + get_repeat_val("after-timeout") + ) + ctest_args += ["--repeat"] + repeat_args if len(repeat_args) > 0 else [] + + return [cdash_args, cmake_args, ctest_args] + + +def run(*args, **kwargs): + import subprocess + + return subprocess.run(*args, **kwargs) + + +if __name__ == "__main__": + args, cmake_args, ctest_args = parse_args() + + if args.clean and os.path.exists(args.binary_dir): + if args.source_dir == args.binary_dir: + raise RuntimeError( + f"cannot clean binary directory == source directory ({args.source_dir})" + ) + + shutil.rmtree(args.binary_dir) + + if not os.path.exists(args.binary_dir): + os.makedirs(args.binary_dir) + + from textwrap import dedent + + _config = dedent(generate_custom(args, cmake_args, ctest_args)) + _script = dedent(generate_dashboard_script(args)) + + if not args.quiet: + sys.stderr.write(f"##### CTestCustom.cmake #####\n\n{_config}\n\n") + sys.stderr.write(f"##### dashboard.cmake #####\n\n{_script}\n\n") + + with open(os.path.join(args.binary_dir, "CTestCustom.cmake"), "w") as f: + f.write(f"{_config}\n") + + with open(os.path.join(args.binary_dir, "dashboard.cmake"), "w") as f: + f.write(f"{_script}\n") + + CTEST_CMD = which("ctest", require=True) + + dashboard_args = ["-D"] + for itr in args.stages: + dashboard_args.append(f"{args.mode}{itr}") + + try: + if not args.quiet and len(ctest_args) == 0: + ctest_args = ["--output-on-failure", "-V"] + + run( + [CTEST_CMD] + + dashboard_args + + [ + "-S", + os.path.join(args.binary_dir, "dashboard.cmake"), + ] + + ctest_args, + check=True, + ) + finally: + echo_files = [] + if "-VV" not in ctest_args and not args.quiet: + for file in glob.glob( + os.path.join(args.binary_dir, "Testing/Temporary/**"), + recursive=True, + ): + if not os.path.isfile(file): + continue + if re.match( + r"Last(Start|Update|Configure|Build|Test).*\.log$", + os.path.basename(file), + ) is None and "MemoryChecker" not in os.path.basename(file): + continue + + echo_files.append(file) + + if echo_files: + # sort alphabetically + echo_files = sorted(echo_files) + echo_files_sorted = [] + # loop over order we want + for key in [ + "LastStart", + "LastUpdate", + "LastConfigure", + "LastBuild", + "LastTest", + ]: + for file in echo_files: + # if key in file, append + if key in file: + echo_files_sorted.append(file) + echo_files_sorted += [x for x in echo_files if x not in echo_files_sorted] + for file in echo_files_sorted: + print(f"\n\n\n###### Reading {file}... ######\n\n\n") + with open(file, "r") as inpf: + fdata = inpf.read() + oname = os.path.basename(file) + if "LastTest" not in oname and "Coverage" not in oname: + print(fdata) + if oname.endswith(".log"): + oname += ".log" + with open(os.path.join(args.binary_dir, oname), "w") as outf: + print(f"\n\n###### Writing {oname}... ######\n\n") + outf.write(fdata) diff --git a/scripts/thread-sanitizer-suppr.txt b/scripts/thread-sanitizer-suppr.txt new file mode 100644 index 0000000000..e1d7b14d74 --- /dev/null +++ b/scripts/thread-sanitizer-suppr.txt @@ -0,0 +1,3 @@ +# +# ThreadSanitizer suppressions file for rocprofiler-register project. +# diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 0000000000..e8fa6d76bb --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# +# +rocprofiler_register_activate_clang_tidy() + +if(ROCPROFILER_REGISTER_BUILD_CODECOV) + set(CMAKE_BUILD_TYPE "Coverage") +endif() + +add_subdirectory(include) +add_subdirectory(lib) diff --git a/source/include/CMakeLists.txt b/source/include/CMakeLists.txt new file mode 100644 index 0000000000..fd82437f6e --- /dev/null +++ b/source/include/CMakeLists.txt @@ -0,0 +1,4 @@ +# +# +# +add_subdirectory(rocprofiler-register) diff --git a/source/include/rocprofiler-register/CMakeLists.txt b/source/include/rocprofiler-register/CMakeLists.txt new file mode 100644 index 0000000000..fbdbae1cae --- /dev/null +++ b/source/include/rocprofiler-register/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# +# Installation of public headers +# +# +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY) + +set(ROCPROFILER_REGISTER_INCLUDE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rocprofiler-register.h + ${CMAKE_CURRENT_BINARY_DIR}/version.h) + +install(FILES ${ROCPROFILER_REGISTER_INCLUDE_FILES} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocprofiler-register) diff --git a/source/include/rocprofiler-register/rocprofiler-register.h b/source/include/rocprofiler-register/rocprofiler-register.h new file mode 100644 index 0000000000..b49c1c8cdb --- /dev/null +++ b/source/include/rocprofiler-register/rocprofiler-register.h @@ -0,0 +1,188 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*rocprofiler_configure_callback_t)(void*); + +typedef struct +{ + rocprofiler_configure_callback_t initialize; + rocprofiler_configure_callback_t finalize; + void* user_data; +} rocprofiler_configure_result_t; + +typedef uint32_t (*rocprofiler_register_import_func_t)(void); + +typedef struct +{ + uint64_t handle; +} rocprofiler_register_library_indentifier_t; + +/// @enum rocprofiler_register_error_code_t +/// @brief enumeration of error codes +/// +/// @var ROCP_REG_SUCCESS +/// @brief Successful call to rocprofiler-register +/// +/// @var ROCP_REG_NO_TOOLS +/// @brief API table was not passed to rocprofiler because no rocprofiler tool +/// configuration symbols were requested +/// +/// @var ROCP_REG_DEADLOCK +/// @brief The thread that is currently communicating the API tables to rocprofiler +/// re-entered \ref rocprofiler_register_library_api_table +/// +/// @var ROCP_REG_BAD_API_TABLE_LENGTH +/// @brief Library provided an invalid API table length (likely zero) +/// +/// @var ROCP_REG_UNSUPPORTED_API +/// @brief Library is providing an API table name that is not supported +/// +/// @var ROCP_REG_ROCPROFILER_ERROR +/// @brief Rocprofiler returned an error when passing the API tables +/// +/// @var ROCP_REG_EXCESS_API_INSTANCES +/// @brief The same API has been registered too many times +/// +typedef enum rocprofiler_register_error_code_t // NOLINT(performance-enum-size) +{ + ROCP_REG_SUCCESS = 0, + ROCP_REG_NO_TOOLS, + ROCP_REG_DEADLOCK, + ROCP_REG_BAD_API_TABLE_LENGTH, + ROCP_REG_UNSUPPORTED_API, + ROCP_REG_INVALID_API_ADDRESS, + ROCP_REG_ROCPROFILER_ERROR, + ROCP_REG_EXCESS_API_INSTANCES, + ROCP_REG_ERROR_CODE_END, +} rocprofiler_register_error_code_t; + +/// @fn rocprofiler_register_error_code_t rocprofiler_register_library_api_table( +/// const char* lib_name, +/// rocprofiler_register_import_func_t import_func, +/// uint32_t lib_version, +/// void* api_tables, +/// uint64_t api_table_length, +/// rocprofiler_register_library_indentifier_t* register_id) +/// @param[in] lib_name string identifier for the library registering the API table +/// @param[in] import_func function pointer to rocprofiler_register_import_ +/// symbol +/// @param[in] lib_version lib version in form of (10000 * major ) + (100 * minor) + patch +/// @param[in] api_tables pointer to one or more API table pointers +/// @param[in] api_table_length number of API tables that are being passed in. Must be > 0 +/// @param[out] register_id a unique identifier for this library encoding the API category +/// and the priority in the event that multiple libraries register with the same name +/// @returns value of type @ref rocprofiler_register_error_code_t +/// +/// @brief primary function call that needs to be performed when the API table of the +/// library is initialized. +/// +rocprofiler_register_error_code_t +rocprofiler_register_library_api_table( + const char* lib_name, + rocprofiler_register_import_func_t import_func, + uint32_t lib_version, + void** api_tables, + uint64_t api_table_length, + rocprofiler_register_library_indentifier_t* register_id) + ROCPROFILER_REGISTER_ATTRIBUTE(nonnull(4, 6)) ROCPROFILER_REGISTER_PUBLIC_API; + +const char* rocprofiler_register_error_string(rocprofiler_register_error_code_t) + ROCPROFILER_REGISTER_PUBLIC_API; + +#ifdef __cplusplus +} +#endif + +/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_1 +/// @param[in] MAJOR_VERSION major version of library (integral) +/// @brief Helper macro for users to generate versioning int expected by +/// rocprofiler-register when the library only maintains a major version number +#define ROCPROFILER_REGISTER_COMPUTE_VERSION_1(MAJOR_VERSION) (10000 * MAJOR_VERSION) + +/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_ +/// @param[in] MAJOR_VERSION major version of library (integral) +/// @param[in] MINOR_VERSION minor version of library (integral) +/// @brief Helper macro for users to generate versioning int expected by +/// rocprofiler-register when the library only maintains a major and minor version number +#define ROCPROFILER_REGISTER_COMPUTE_VERSION_2(MAJOR_VERSION, MINOR_VERSION) \ + (ROCPROFILER_REGISTER_COMPUTE_VERSION_1(MAJOR_VERSION) + (100 * MINOR_VERSION)) + +/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_3 +/// @param[in] MAJOR_VERSION major version of library (integral) +/// @param[in] MINOR_VERSION minor version of library (integral) +/// @param[in] PATCH_VERSION patch version of library (integral) +/// @brief Helper macro for users to generate versioning int expected by +/// rocprofiler-register when the library maintains a major, minor, and patch version +/// numbers +#define ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \ + MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION) \ + (ROCPROFILER_REGISTER_COMPUTE_VERSION_2(MAJOR_VERSION, MINOR_VERSION) + \ + (PATCH_VERSION)) + +/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_4 +/// @param[in] MAJOR_VERSION major version of library (integral) +/// @param[in] MINOR_VERSION minor version of library (integral) +/// @param[in] PATCH_VERSION patch version of library (integral) +/// @param[in] TWEAK_VERSION tweak version of library which will be ignored +/// @brief Helper macro for users to generate versioning int expected by +/// rocprofiler-register when the library maintains a major, minor, patch, and tweak +/// version numbers +#define ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \ + MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION) \ + (ROCPROFILER_REGISTER_COMPUTE_VERSION_2(MAJOR_VERSION, MINOR_VERSION) + \ + (PATCH_VERSION)) + +/// @def ROCPROFILER_REGISTER_IMPORT_FUNC(NAME) +/// @param[in] NAME the string identifier for the library +/// @brief Helper macro for retrieving the name of the import function which is used by +/// rocprofiler-register to identify the location and priority of the registering library +#define ROCPROFILER_REGISTER_IMPORT_FUNC(NAME) \ + ROCPROFILER_REGISTER_PP_COMBINE(rocprofiler_register_import_, NAME) + +/// @def ROCPROFILER_REGISTER_DEFINE_IMPORT(NAME, VERSION) +/// @param[in] NAME the unquoted string identifier for the library, e.g. hip +/// @brief Helper macro for declaring a visible import symbol for rocprofiler-register +/// which returns the version. +/// +#ifdef __cplusplus +# define ROCPROFILER_REGISTER_DEFINE_IMPORT(NAME, VERSION) \ + extern "C" { \ + uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)() \ + ROCPROFILER_REGISTER_ATTRIBUTE(visibility("default")); \ + \ + uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)() { return VERSION; } \ + } +#else +# define ROCPROFILER_REGISTER_DEFINE_IMPORT(NAME, VERSION) \ + uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)(void) \ + ROCPROFILER_REGISTER_ATTRIBUTE(visibility("default")); \ + \ + uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)(void) { return VERSION; } +#endif diff --git a/source/include/rocprofiler-register/version.h.in b/source/include/rocprofiler-register/version.h.in new file mode 100644 index 0000000000..76239994fd --- /dev/null +++ b/source/include/rocprofiler-register/version.h.in @@ -0,0 +1,103 @@ +// 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 + +// clang-format off +#define ROCPROFILER_REGISTER_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define ROCPROFILER_REGISTER_VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define ROCPROFILER_REGISTER_VERSION_PATCH @PROJECT_VERSION_PATCH@ +#define ROCPROFILER_REGISTER_VERSION_STRING "@FULL_VERSION_STRING@" +#define ROCPROFILER_REGISTER_SOVERSION "@PROJECT_VERSION_MAJOR@" +#define ROCPROFILER_REGISTER_GIT_DESCRIBE "@ROCPROFILER_REGISTER_GIT_DESCRIBE@" +#define ROCPROFILER_REGISTER_GIT_REVISION "@ROCPROFILER_REGISTER_GIT_REVISION@" + +// system info during compilation +#define ROCPROFILER_REGISTER_LIBRARY_ARCH "@CMAKE_LIBRARY_ARCHITECTURE@" +#define ROCPROFILER_REGISTER_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@" +#define ROCPROFILER_REGISTER_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@" +#define ROCPROFILER_REGISTER_SYSTEM_VERSION "@CMAKE_SYSTEM_VERSION@" + +// compiler information +#define ROCPROFILER_REGISTER_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@" +#define ROCPROFILER_REGISTER_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@" +#define ROCPROFILER_REGISTER_COMPILER_STRING ROCPROFILER_REGISTER_COMPILER_ID " v" ROCPROFILER_REGISTER_COMPILER_VERSION +// clang-format on + +#define ROCPROFILER_REGISTER_VERSION \ + ((10000 * ROCPROFILER_REGISTER_VERSION_MAJOR) + \ + (100 * ROCPROFILER_REGISTER_VERSION_MINOR) + ROCPROFILER_REGISTER_VERSION_PATCH) + +#define ROCPROFILER_REGISTER_ATTRIBUTE(...) __attribute__((__VA_ARGS__)) +#define ROCPROFILER_REGISTER_PP_COMBINE(X, Y) X##Y + +#if defined(rocprofiler_register_EXPORTS) +// only defined in build tree +# define ROCPROFILER_REGISTER_VISIBILITY(MODE) \ + ROCPROFILER_REGISTER_ATTRIBUTE(visibility(MODE)) +# define ROCPROFILER_REGISTER_PUBLIC_API ROCPROFILER_REGISTER_VISIBILITY("default") +# define ROCPROFILER_REGISTER_HIDDEN_API ROCPROFILER_REGISTER_VISIBILITY("hidden") +# define ROCPROFILER_REGISTER_INTERNAL_API ROCPROFILER_REGISTER_VISIBILITY("internal") +# define ROCPROFILER_REGISTER_INLINE \ + ROCPROFILER_REGISTER_ATTRIBUTE(always_inline) inline +# define ROCPROFILER_REGISTER_NOINLINE ROCPROFILER_REGISTER_ATTRIBUTE(noinline) +# define ROCPROFILER_REGISTER_HOT ROCPROFILER_REGISTER_ATTRIBUTE(hot) +# define ROCPROFILER_REGISTER_COLD ROCPROFILER_REGISTER_ATTRIBUTE(cold) +# define ROCPROFILER_REGISTER_CONST ROCPROFILER_REGISTER_ATTRIBUTE(const) +# define ROCPROFILER_REGISTER_PURE ROCPROFILER_REGISTER_ATTRIBUTE(pure) +# define ROCPROFILER_REGISTER_WEAK ROCPROFILER_REGISTER_ATTRIBUTE(weak) +# define ROCPROFILER_REGISTER_PACKED ROCPROFILER_REGISTER_ATTRIBUTE(__packed__) +# define ROCPROFILER_REGISTER_PACKED_ALIGN(VAL) \ + ROCPROFILER_REGISTER_PACKED ROCPROFILER_REGISTER_ATTRIBUTE(__aligned__(VAL)) +# define ROCPROFILER_REGISTER_LIKELY(...) __builtin_expect((__VA_ARGS__), 1) +# define ROCPROFILER_REGISTER_UNLIKELY(...) __builtin_expect((__VA_ARGS__), 0) + +# if defined(ROCPROFILER_REGISTER_CI) && ROCPROFILER_REGISTER_CI > 0 +# if defined(NDEBUG) +# undef NDEBUG +# endif +# if !defined(DEBUG) +# define DEBUG 1 +# endif +# if defined(__cplusplus) +# include // NOLINT +# else +# include +# endif +# endif + +# define ROCPROFILER_REGISTER_STRINGIZE(X) ROCPROFILER_REGISTER_STRINGIZE2(X) +# define ROCPROFILER_REGISTER_STRINGIZE2(X) # X +# define ROCPROFILER_REGISTER_LINESTR ROCPROFILER_REGISTER_STRINGIZE(__LINE__) +# define ROCPROFILER_REGISTER_ESC(...) __VA_ARGS__ + +# if defined(__cplusplus) +# if !defined(ROCPROFILER_REGISTER_FOLD_EXPRESSION) +# define ROCPROFILER_REGISTER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...) +# endif +# endif +#else +# define ROCPROFILER_REGISTER_VISIBILITY(MODE) +# define ROCPROFILER_REGISTER_PUBLIC_API +# define ROCPROFILER_REGISTER_HIDDEN_API +# define ROCPROFILER_REGISTER_INTERNAL_API +#endif diff --git a/source/lib/CMakeLists.txt b/source/lib/CMakeLists.txt new file mode 100644 index 0000000000..fd82437f6e --- /dev/null +++ b/source/lib/CMakeLists.txt @@ -0,0 +1,4 @@ +# +# +# +add_subdirectory(rocprofiler-register) diff --git a/source/lib/rocprofiler-register/CMakeLists.txt b/source/lib/rocprofiler-register/CMakeLists.txt new file mode 100644 index 0000000000..f1464bad77 --- /dev/null +++ b/source/lib/rocprofiler-register/CMakeLists.txt @@ -0,0 +1,36 @@ +# +# builds the rocprofiler-register library +# +add_library(rocprofiler-register SHARED) +add_library(rocprofiler-register::rocprofiler-register ALIAS rocprofiler-register) + +add_subdirectory(details) + +target_sources(rocprofiler-register PRIVATE rocprofiler_register.cpp) + +if(ROCPROFILER_REGISTER_BUILD_TESTS) + # make sure header is C-compatible + target_sources(rocprofiler-register PRIVATE rocprofiler_register.c) +endif() + +target_include_directories( + rocprofiler-register PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/source + ${PROJECT_BINARY_DIR}/source) + +target_link_libraries( + rocprofiler-register + PUBLIC rocprofiler-register::headers + PRIVATE rocprofiler-register::build-flags rocprofiler-register::memcheck + rocprofiler-register::stdcxxfs rocprofiler-register::dl) + +set_target_properties( + rocprofiler-register + PROPERTIES OUTPUT_NAME rocprofiler-register + SOVERSION ${PROJECT_VERSION_MAJOR} + VERSION ${PROJECT_VERSION}) + +install( + TARGETS rocprofiler-register + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT core + EXPORT ${PROJECT_NAME}-library-targets) diff --git a/source/lib/rocprofiler-register/details/CMakeLists.txt b/source/lib/rocprofiler-register/details/CMakeLists.txt new file mode 100644 index 0000000000..19f7c15568 --- /dev/null +++ b/source/lib/rocprofiler-register/details/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# builds the rocprofiler-register library +# +set(rocprofiler_register_details_sources dl.cpp utility.cpp) + +set(rocprofiler_register_details_headers environment.hpp join.hpp dl.hpp log.hpp + utility.hpp) + +target_sources(rocprofiler-register PRIVATE ${rocprofiler_register_details_sources} + ${rocprofiler_register_details_headers}) diff --git a/source/lib/rocprofiler-register/details/dl.cpp b/source/lib/rocprofiler-register/details/dl.cpp new file mode 100644 index 0000000000..3ae00a688e --- /dev/null +++ b/source/lib/rocprofiler-register/details/dl.cpp @@ -0,0 +1,125 @@ +// 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 GNU_SOURCE 1 + +#include "dl.hpp" +#include "join.hpp" +#include "utility.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace fs = ::std::filesystem; + +namespace rocprofiler_register +{ +namespace binary +{ +namespace +{ +const open_modes_vec_t default_link_open_modes = { (RTLD_LAZY | RTLD_NOLOAD), + (RTLD_LAZY | RTLD_LOCAL) }; +} // namespace + +std::vector +get_segment_addresses(pid_t _pid) +{ + auto _data = std::vector{}; + auto _fname = common::join('/', "/proc", _pid, "maps"); + auto ifs = std::ifstream{ _fname }; + if(!ifs) + { + fprintf(stderr, "Failure opening %s\n", _fname.c_str()); + } + else + { + auto _get_entry = [&_data](std::string_view _name) -> segment_address_ranges& { + for(auto& itr : _data) + { + if(itr.filepath == _name) return itr; + } + return _data.emplace_back( + segment_address_ranges{ .filepath = std::string{ _name } }); + }; + + while(ifs) + { + std::string _line = {}; + if(std::getline(ifs, _line) && !_line.empty()) + { + auto _delim = utility::delimit(_line, " \t\n\r"); + if(_delim.size() > 5 && fs::exists(fs::path{ _delim.back() })) + { + auto& _entry = _get_entry(_delim.back()); + auto _addr = utility::delimit(_delim.front(), "-"); + auto load_address = std::stoull(_addr.front(), nullptr, 16); + auto last_address = std::stoull(_addr.back(), nullptr, 16); + _entry.ranges.emplace_back( + address_range{ load_address, last_address }); + } + } + } + } + return _data; +} + +std::optional +get_linked_path(std::string_view _name, open_modes_vec_t&& _open_modes) +{ + if(_name.empty()) return fs::current_path().string(); + + if(_open_modes.empty()) _open_modes = default_link_open_modes; + + void* _handle = nullptr; + bool _noload = false; + for(auto _mode : _open_modes) + { + _handle = dlopen(_name.data(), _mode); + _noload = (_mode & RTLD_NOLOAD) == RTLD_NOLOAD; + if(_handle) break; + } + + if(_handle) + { + struct link_map* _link_map = nullptr; + dlinfo(_handle, RTLD_DI_LINKMAP, &_link_map); + if(_link_map != nullptr && !std::string_view{ _link_map->l_name }.empty()) + { + return fs::absolute(fs::path{ _link_map->l_name }).string(); + } + if(_noload == false) dlclose(_handle); + } + + return std::nullopt; +} +} // namespace binary +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/details/dl.hpp b/source/lib/rocprofiler-register/details/dl.hpp new file mode 100644 index 0000000000..bfded01a8d --- /dev/null +++ b/source/lib/rocprofiler-register/details/dl.hpp @@ -0,0 +1,60 @@ +// 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 +#include +#include +#include +#include + +#include +#include +#include + +namespace rocprofiler_register +{ +namespace binary +{ +using open_modes_vec_t = std::vector; + +struct address_range +{ + uintptr_t start = 0; + uintptr_t last = 0; +}; + +struct segment_address_ranges +{ + std::string filepath = {}; + std::vector ranges = {}; +}; + +std::vector +get_segment_addresses(pid_t _pid = getpid()); + +// helper function for translating generic lib name to resolved path +std::optional +get_linked_path(std::string_view, open_modes_vec_t&& = {}); +} // namespace binary +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/details/environment.hpp b/source/lib/rocprofiler-register/details/environment.hpp new file mode 100644 index 0000000000..03bcf47089 --- /dev/null +++ b/source/lib/rocprofiler-register/details/environment.hpp @@ -0,0 +1,191 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 "log.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_NAME) +# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_NAME) +# define ROCPROFILER_REGISTER_ENVIRON_LOG_NAME \ + "[" ROCPROFILER_REGISTER_COMMON_LIBRARY_NAME "]" +# else +# define ROCPROFILER_REGISTER_ENVIRON_LOG_NAME "[environ]" +# endif +#endif + +#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_START) +# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_START) +# define ROCPROFILER_REGISTER_ENVIRON_LOG_START \ + ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_START +# elif defined(ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE) +# define ROCPROFILER_REGISTER_ENVIRON_LOG_START \ + fprintf(stderr, "%s", ::rocprofiler_register::log::color::dmesg()); +# else +# define ROCPROFILER_REGISTER_ENVIRON_LOG_START +# endif +#endif + +#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_END) +# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_END) +# define ROCPROFILER_REGISTER_ENVIRON_LOG_END \ + ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_END +# elif defined(ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE) +# define ROCPROFILER_REGISTER_ENVIRON_LOG_END \ + fprintf(stderr, "%s", ::rocprofiler_register::log::color::end()); +# else +# define ROCPROFILER_REGISTER_ENVIRON_LOG_END +# endif +#endif + +#define ROCPROFILER_REGISTER_ENVIRON_LOG(CONDITION, ...) \ + if(CONDITION) \ + { \ + fflush(stderr); \ + ROCPROFILER_REGISTER_ENVIRON_LOG_START \ + fprintf(stderr, \ + "[rocprofiler-register]" ROCPROFILER_REGISTER_ENVIRON_LOG_NAME "[%i] ", \ + getpid()); \ + fprintf(stderr, __VA_ARGS__); \ + ROCPROFILER_REGISTER_ENVIRON_LOG_END \ + fflush(stderr); \ + } + +namespace rocprofiler_register +{ +namespace common +{ +namespace +{ +inline std::string +get_env_impl(std::string_view env_id, std::string_view _default) +{ + if(env_id.empty()) return std::string{ _default }; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) return std::string{ env_var }; + return std::string{ _default }; +} + +inline std::string +get_env_impl(std::string_view env_id, const char* _default) +{ + return get_env_impl(env_id, std::string_view{ _default }); +} + +inline int +get_env_impl(std::string_view env_id, int _default) +{ + if(env_id.empty()) return _default; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) + { + try + { + return std::stoi(env_var); + } catch(std::exception& _e) + { + fprintf(stderr, + "[rocprofiler_register][get_env] Exception thrown converting " + "getenv(\"%s\") = " + "%s to integer :: %s. Using default value of %i\n", + env_id.data(), + env_var, + _e.what(), + _default); + } + return _default; + } + return _default; +} + +inline bool +get_env_impl(std::string_view env_id, bool _default) +{ + if(env_id.empty()) return _default; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) + { + if(std::string_view{ env_var }.empty()) + { + throw std::runtime_error(std::string{ "No boolean value provided for " } + + std::string{ env_id }); + } + + if(std::string_view{ env_var }.find_first_not_of("0123456789") == + std::string_view::npos) + { + return static_cast(std::stoi(env_var)); + } + + 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 + +template +inline auto +get_env(std::string_view env_id, Tp&& _default) +{ + if constexpr(std::is_enum::value) + { + using Up = std::underlying_type_t; + // cast to underlying type -> get_env -> cast to enum type + return static_cast(get_env_impl(env_id, static_cast(_default))); + } + else + { + return get_env_impl(env_id, std::forward(_default)); + } +} + +struct env_config +{ + std::string env_name = {}; + std::string env_value = {}; + int override = 0; + + auto operator()(bool _verbose = false) const + { + if(env_name.empty()) return -1; + ROCPROFILER_REGISTER_ENVIRON_LOG(_verbose, + "setenv(\"%s\", \"%s\", %i)\n", + env_name.c_str(), + env_value.c_str(), + override); + return setenv(env_name.c_str(), env_value.c_str(), override); + } +}; +} // namespace common +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/details/join.hpp b/source/lib/rocprofiler-register/details/join.hpp new file mode 100644 index 0000000000..0086560dcf --- /dev/null +++ b/source/lib/rocprofiler-register/details/join.hpp @@ -0,0 +1,184 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +#if !defined(ROCPROFILER_REGISTER_FOLD_EXPRESSION) +# define ROCPROFILER_REGISTER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...) +#endif + +namespace rocprofiler_register +{ +namespace common +{ +namespace +{ +template +struct is_string_impl : std::false_type +{ }; + +template <> +struct is_string_impl : std::true_type +{ }; + +template <> +struct is_string_impl : std::true_type +{ }; + +template <> +struct is_string_impl : std::true_type +{ }; + +template <> +struct is_string_impl : std::true_type +{ }; + +template +struct is_string : is_string_impl>> +{ }; + +template +auto +as_string(ArgT&& _v, std::enable_if_t::value, int> = 0) +{ + if constexpr(std::is_pointer>::value) + { + return (_v == nullptr) ? std::string{ "\"\"" } + : (std::string{ "\"" } + _v + std::string{ "\"" }); + } + else + { + return std::string{ "\"" } + _v + std::string{ "\"" }; + } +} + +template +auto +as_string(ArgT&& _v, std::enable_if_t::value, long> = 0) +{ + return _v; +} + +template +auto +join(DelimT&& _delim, Args&&... _args) +{ + using delim_type = std::remove_cv_t>; + + std::stringstream _ss{}; + _ss << std::boolalpha; + + if constexpr(std::is_same::value) + { + const char _delim_c[2] = { _delim, '\0' }; + ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim_c << _args); + auto _ret = _ss.str(); + return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; + } + else + { + ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim << _args); + auto _ret = _ss.str(); + auto&& _len = std::string{ _delim }.length(); + return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; + } +} + +struct QuoteStrings +{ }; + +template +auto +join(QuoteStrings&&, DelimT&& _delim, Args&&... _args) +{ + using delim_type = std::remove_cv_t>; + + std::stringstream _ss{}; + _ss << std::boolalpha; + + if constexpr(std::is_same::value) + { + const char _delim_c[2] = { _delim, '\0' }; + ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim_c << as_string(_args)); + auto _ret = _ss.str(); + return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; + } + else + { + ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim << as_string(_args)); + auto _ret = _ss.str(); + auto&& _len = std::string{ _delim }.length(); + return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; + } +} + +template +auto +join(std::array&& _delim, Args&&... _args) +{ + return join("", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} + +template +auto +join(QuoteStrings&&, std::array&& _delim, Args&&... _args) +{ + return join(QuoteStrings{}, + "", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} + +template +auto +join(std::tuple&& _delim, Args&&... _args) +{ + return join("", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} + +template +auto +join(QuoteStrings&&, std::tuple&& _delim, Args&&... _args) +{ + return join(QuoteStrings{}, + "", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} +} // namespace +} // namespace common +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/details/log.hpp b/source/lib/rocprofiler-register/details/log.hpp new file mode 100644 index 0000000000..bc9ecf7c75 --- /dev/null +++ b/source/lib/rocprofiler-register/details/log.hpp @@ -0,0 +1,518 @@ +// 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 rhs +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR rhsWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR rhs DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include + +#ifndef ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE +# define ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE 1 +#endif + +#ifndef ROCPROFILER_REGISTER_PROJECT_NAME +# define ROCPROFILER_REGISTER_PROJECT_NAME "rocprofiler-register" +#endif + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler_register +{ +namespace log +{ +bool& +monochrome(); + +inline bool& +monochrome() +{ + static bool _v = []() { + auto _val = false; + const char* _env_cstr = nullptr; + _env_cstr = std::getenv("ROCPROFILER_REGISTER_MONOCHROME"); + + if(!_env_cstr) _env_cstr = std::getenv("MONOCHROME"); + + if(_env_cstr) + { + auto _env = std::string{ _env_cstr }; + + // check if numeric + if(_env.find_first_not_of("0123456789") == std::string::npos) + { + return _env.length() > 1 || _env[0] != '0'; + } + + for(auto& itr : _env) + itr = tolower(itr); + + // check for matches to acceptable forms of false + for(const auto& itr : { "off", "false", "no", "n", "f" }) + { + if(_env == itr) return false; + } + + // check for matches to acceptable forms of true + for(const auto& itr : { "on", "true", "yes", "y", "t" }) + { + if(_env == itr) return true; + } + } + return _val; + }(); + return _v; +} + +namespace color +{ +static constexpr auto info_value = "\033[01;34m"; +static constexpr auto warning_value = "\033[01;33m"; +static constexpr auto fatal_value = "\033[01;31m"; +static constexpr auto source_value = "\033[01;32m"; +static constexpr auto dmesg_value = "\033[01;37m"; +static constexpr auto end_value = "\033[0m"; + +inline const char* +info() +{ + return (log::monochrome()) ? "" : info_value; +} + +inline const char* +warning() +{ + return (log::monochrome()) ? "" : warning_value; +} + +inline const char* +fatal() +{ + return (log::monochrome()) ? "" : fatal_value; +} + +inline const char* +source() +{ + return (log::monochrome()) ? "" : source_value; +} + +inline const char* +dmesg() +{ + return (log::monochrome()) ? "" : dmesg_value; +} + +inline const char* +end() +{ + return (log::monochrome()) ? "" : end_value; +} +} // namespace color +} // namespace log +} // namespace rocprofiler_register + +namespace rocprofiler_register +{ +namespace log +{ +struct base +{ +public: + static base indent(size_t, size_t = 2) { return base{}; } + + template + auto operator<<(Tp&&) + { + return base{}; + } +}; + +struct logger : public base +{ + logger() = default; + + explicit logger(bool _exit) + : m_exit{ _exit } + { } + + ~logger() + { + if(m_done) + { + std::cerr << color::end() << "\n"; + if(m_exit) abort(); + } + } + + logger(logger&& rhs) noexcept + { + m_exit = rhs.m_exit; + m_done = rhs.m_done; + rhs.m_done = false; + } + + logger& operator=(logger&& rhs) noexcept + { + m_exit = rhs.m_exit; + m_done = rhs.m_done; + rhs.m_done = false; + return *this; + } + + logger&& indent(size_t _n, size_t _tab_size = 4) + { + for(size_t i = 0; i < _n; i++) + for(size_t j = 0; j < _tab_size; j++) + std::cerr << " "; + return std::move(*this); + } + + template + logger&& operator<<(Tp&& _v) + { + std::cerr << std::forward(_v); + return std::move(*this); + } + +private: + bool m_exit = false; + bool m_done = true; +}; + +template +inline auto& +get_color_hist() +{ + static thread_local std::vector> _v{}; + return _v; +} + +template +inline auto +push_color_hist(Tp* _v, const char* _c) +{ + if(!monochrome()) get_color_hist().emplace_back(_v, _c); + return _c; +} + +template +inline std::string +pop_color_hist(Tp* _v) +{ + if(monochrome()) return std::string{}; + + auto& _hist = get_color_hist(); + for(auto itr = _hist.rbegin(); itr != _hist.rend(); ++itr) + { + Tp* _addr = itr->first; + if(_addr == _v) + { + auto fitr = _hist.begin(); + std::advance(fitr, std::distance(_hist.rbegin(), itr)); + _hist.erase(fitr); + } + } + for(auto itr = _hist.rbegin(); itr != _hist.rend(); ++itr) + { + if(itr->first == _v) return itr->second; + } + return color::end(); +} + +template +std::basic_ostream& +info(std::basic_ostream& os) +{ + return (os << push_color_hist(&os, color::info())); +} + +template +std::basic_ostream& +warning(std::basic_ostream& os) +{ + return (os << push_color_hist(&os, color::warning())); +} + +template +std::basic_ostream& +fatal(std::basic_ostream& os) +{ + return (os << push_color_hist(&os, color::fatal())); +} + +template +std::basic_ostream& +source(std::basic_ostream& os) +{ + return (os << push_color_hist(&os, color::source())); +} + +template +std::basic_ostream& +end(std::basic_ostream& os) +{ + return (os << push_color_hist(&os, color::end())); +} + +template +std::basic_ostream& +pop(std::basic_ostream& os) +{ + return (os << pop_color_hist(&os)); +} + +template +std::basic_ostream& +reset(std::basic_ostream& os) +{ + pop_color_hist(&os); + return (os << color::end()); +} + +template +std::basic_ostream& +flush(std::basic_ostream& os) +{ + return (os << pop << std::flush); +} + +template +std::basic_ostream& +endl(std::basic_ostream& os) +{ + return (os << pop << "\n" << std::flush); +} + +template +struct stream_base +{ + stream_base(StreamT& _os, const char* _color) + : m_os{ _os } + { + m_os << push_color_hist(&_os, _color); + } + + ~stream_base() { m_os << pop_color_hist(&m_os); } + + stream_base(const stream_base&) = delete; + stream_base& operator=(const stream_base&) = delete; + + stream_base(stream_base&& rhs) noexcept = default; + stream_base& operator=(stream_base&& rhs) noexcept = default; + + template + stream_base& operator<<(Tp&& _v) + { + m_os << std::forward(_v); + return *this; + } + + template + stream_base& operator<<(Tp& _v) + { + m_os << _v; + return *this; + } + + stream_base& put(char _c) + { + m_os.put(_c); + return *this; + } + + stream_base& endl() + { + m_os << std::endl; + return *this; + } + + template + stream_base& write(Args&&... _args) + { + m_os.write(std::forward(_args)...); + return *this; + } + + stream_base& flush() + { + m_os << std::flush; + return *this; + } + + auto tellp() { return m_os.tellp(); } + + template + stream_base& seekp(Args&&... _args) + { + m_os.seekp(std::forward(_args)...); + return *this; + } + +private: + StreamT& m_os; +}; + +template +stream_base +stream(StreamT& _os, const char* _color) +{ + return stream_base{ _os, _color }; +} + +template +stream_base +info_stream(StreamT& _os) +{ + return stream_base{ _os, color::info() }; +} + +template +stream_base +source_stream(StreamT& _os) +{ + return stream_base{ _os, color::source() }; +} + +template +stream_base +warning_stream(StreamT& _os) +{ + return stream_base{ _os, color::warning() }; +} + +template +stream_base +fatal_stream(StreamT& _os) +{ + return stream_base{ _os, color::fatal() }; +} + +inline std::string +string(const char* _color, std::string_view _v) +{ + return std::string{ _color } + std::string{ _v } + std::string{ color::end() }; +} + +inline std::string +string(const char* _color, std::stringstream& _v) +{ + return std::string{ _color } + _v.str() + std::string{ color::end() }; +} + +inline std::string +string(const char* _color, std::stringstream&& _v) +{ + return std::string{ _color } + _v.str() + std::string{ color::end() }; +} + +template +inline auto +info_string(Tp&& _v) +{ + return string(color::info(), std::forward(_v)); +} + +template +inline auto +source_string(Tp&& _v) +{ + return string(color::source(), std::forward(_v)); +} + +template +inline auto +warning_string(Tp&& _v) +{ + return string(color::warning(), std::forward(_v)); +} + +template +inline auto +fatal_string(Tp&& _v) +{ + return string(color::fatal(), std::forward(_v)); +} +} // namespace log +} // namespace rocprofiler_register + +#if !defined(ROCPROFILER_REGISTER_LOG) +# define ROCPROFILER_REGISTER_LOG(COLOR, EXIT_CODE) \ + (::rocprofiler_register::log::logger(EXIT_CODE) \ + << ::rocprofiler_register::log::color::end() \ + << ::rocprofiler_register::log::color::source() << "[" \ + << ROCPROFILER_REGISTER_PROJECT_NAME << "][" << ROCP_REG_FILE_NAME << ":" \ + << __LINE__ << "][" << getpid() << "] " \ + << ::rocprofiler_register::log::color::end() << COLOR) +#endif + +#if defined(NDEBUG) +# if !defined(ROCPROFILER_REGISTER_INFO) +# define ROCPROFILER_REGISTER_INFO (::rocprofiler_register::log::base()) +# endif +# if !defined(ROCPROFILER_REGISTER_ASSERT) +# define ROCPROFILER_REGISTER_ASSERT(COND) (::rocprofiler_register::log::base()) +# endif +#else +# if !defined(ROCPROFILER_REGISTER_INFO) +# define ROCPROFILER_REGISTER_INFO \ + ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::info(), false) +# endif +# if !defined(ROCPROFILER_REGISTER_ASSERT) +# define ROCPROFILER_REGISTER_ASSERT(COND) \ + (COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_FATAL +# endif +#endif + +#if !defined(ROCPROFILER_REGISTER_WARNING) +# define ROCPROFILER_REGISTER_WARNING \ + ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::warning(), false) +#endif + +#if !defined(ROCPROFILER_REGISTER_FATAL) +# define ROCPROFILER_REGISTER_FATAL \ + ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::fatal(), true) +#endif + +#if !defined(ROCPROFILER_REGISTER_PREFER) +# define ROCPROFILER_REGISTER_PREFER(COND) \ + (COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_WARNING +#endif + +#if !defined(ROCPROFILER_REGISTER_REQUIRE) +# define ROCPROFILER_REGISTER_REQUIRE(COND) \ + (COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_FATAL +#endif diff --git a/source/lib/rocprofiler-register/details/utility.cpp b/source/lib/rocprofiler-register/details/utility.cpp new file mode 100644 index 0000000000..7a72ba729d --- /dev/null +++ b/source/lib/rocprofiler-register/details/utility.cpp @@ -0,0 +1,127 @@ +// 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 "utility.hpp" + +#include +#include + +#include +#include + +namespace rocprofiler_register +{ +namespace utility +{ +namespace +{ +template +inline auto +emplace_impl(ContainerT& _c, int, Args&&... _args) + -> decltype(_c.emplace_back(std::forward(_args)...)) +{ + return _c.emplace_back(std::forward(_args)...); +} + +template +inline auto +emplace_impl(ContainerT& _c, long, Args&&... _args) + -> decltype(_c.emplace(std::forward(_args)...)) +{ + return _c.emplace(std::forward(_args)...); +} + +template +inline auto +emplace(ContainerT& _c, Args&&... _args) +{ + return emplace_impl(_c, 0, std::forward(_args)...); +} + +template +inline auto +reserve_impl(ContainerT& _c, int, ArgT _arg) -> decltype(_c.reserve(_arg), bool()) +{ + _c.reserve(_arg); + return true; +} + +template +inline auto +reserve_impl(ContainerT&, long, ArgT) +{ + return false; +} + +template +inline auto +reserve(ContainerT& _c, ArgT _arg) +{ + return reserve_impl(_c, 0, _arg); +} +} // namespace + +template +ContainerT +delimit(const std::string& line, std::string_view 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 + if(reserve(_result, 0)) + { + size_t _nmax = 0; + for(char itr : line) + { + for(size_t j = 0; j < delimiters.length(); ++j) + { + if(itr == delimiters.at(j)) ++_nmax; + } + } + reserve(_result, _nmax); + } + 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()) emplace(_result, _tmp); + } + return _result; +} + +template std::vector +delimit(const std::string&, std::string_view); + +template std::set +delimit(const std::string&, std::string_view); +} // namespace utility +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/details/utility.hpp b/source/lib/rocprofiler-register/details/utility.hpp new file mode 100644 index 0000000000..7600af8b4c --- /dev/null +++ b/source/lib/rocprofiler-register/details/utility.hpp @@ -0,0 +1,44 @@ +// 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 +#include +#include +#include + +namespace rocprofiler_register +{ +namespace utility +{ +template > +ContainerT +delimit(const std::string& line, std::string_view delimiters = "\"',;: "); + +extern template std::vector +delimit(const std::string&, std::string_view); + +extern template std::set +delimit(const std::string&, std::string_view); +} // namespace utility +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/rocprofiler_register.c b/source/lib/rocprofiler-register/rocprofiler_register.c new file mode 100644 index 0000000000..0b3dd6d140 --- /dev/null +++ b/source/lib/rocprofiler-register/rocprofiler_register.c @@ -0,0 +1,24 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 +#include + +int ROCPROFILER_REGISTER_INTERNAL_API rocp_register_sym = 0; diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp new file mode 100644 index 0000000000..55cd1ab4c7 --- /dev/null +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -0,0 +1,374 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 GNU_SOURCE 1 + +#include + +#include "details/dl.hpp" +#include "details/environment.hpp" +#include "details/log.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern "C" { +#pragma weak rocprofiler_configure +#pragma weak rocprofiler_set_api_table +#pragma weak rocprofiler_register_import_hip +#pragma weak rocprofiler_register_import_hip_static +#pragma weak rocprofiler_register_import_hsa +#pragma weak rocprofiler_register_import_hsa_static +#pragma weak rocprofiler_register_import_roctx +#pragma weak rocprofiler_register_import_roctx_static + +extern rocprofiler_configure_result_t* +rocprofiler_configure(uint32_t, const char*, uint32_t, uint32_t); + +extern int +rocprofiler_set_api_table(const char*, uint64_t, uint64_t, void**, uint64_t); + +extern uint32_t +rocprofiler_register_import_hip(void); + +extern uint32_t +rocprofiler_register_import_hsa(void); + +extern uint32_t +rocprofiler_register_import_roctx(void); + +extern uint32_t +rocprofiler_register_import_hip_static(void); + +extern uint32_t +rocprofiler_register_import_hsa_static(void); + +extern uint32_t +rocprofiler_register_import_roctx_static(void); +} + +namespace +{ +namespace fs = ::std::filesystem; +using namespace rocprofiler_register; +using rocprofiler_set_api_table_t = decltype(::rocprofiler_set_api_table)*; +using bitset_t = std::bitset; + +static_assert(sizeof(bitset_t) == + sizeof(rocprofiler_register_library_indentifier_t::handle), + "bitset should be same at uint64_t"); + +int rocprofiler_register_verbose = common::get_env("ROCPROFILER_REGISTER_VERBOSE", 0); +constexpr int rocprofiler_register_info_level = 2; +constexpr auto rocprofiler_lib_name = "librocprofiler64.so"; +constexpr auto rocprofiler_lib_register_entrypoint = "rocprofiler_set_api_table"; +constexpr auto rocprofiler_register_lib_name = + "librocprofiler-register.so." ROCPROFILER_REGISTER_SOVERSION; + +enum rocp_reg_supported_library // NOLINT(performance-enum-size) +{ + ROCP_REG_HSA = 0, + ROCP_REG_HIP, + ROCP_REG_ROCTX, + ROCP_REG_LAST, +}; + +template +struct supported_library_trait +{ + static constexpr bool specialized = false; + static constexpr auto value = ROCP_REG_LAST; + static constexpr const char* const common_name = nullptr; + static constexpr const char* const symbol_name = nullptr; + static constexpr const char* const library_name = nullptr; +}; + +#define ROCP_REG_DEFINE_LIBRARY_TRAITS(ENUM, NAME, SYM_NAME, LIB_NAME) \ + template <> \ + struct supported_library_trait \ + { \ + static constexpr bool specialized = true; \ + static constexpr auto value = ENUM; \ + static constexpr auto common_name = NAME; \ + static constexpr auto symbol_name = SYM_NAME; \ + static constexpr auto library_name = LIB_NAME; \ + }; + +ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_HSA, + "hsa", + "rocprofiler_register_import_hsa", + "libhsa-runtime64.so.[2-9]($|\\.[0-9\\.]+)") + +ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_HIP, + "hip", + "rocprofiler_register_import_hip", + "libamdhip64.so.[6-9]($|\\.[0-9\\.]+)") + +ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_ROCTX, + "roctx", + "rocprofiler_register_import_roctx", + "libroctx64.so.[4-9]($|\\.[0-9\\.]+)") + +auto +get_this_library_path() +{ + auto _this_lib_path = binary::get_linked_path(rocprofiler_register_lib_name, + { RTLD_NOLOAD | RTLD_LAZY }); + ROCPROFILER_REGISTER_REQUIRE(_this_lib_path) + << rocprofiler_register_lib_name + << " could not locate itself in the list of loaded libraries"; + return fs::path{ *_this_lib_path }.parent_path().string(); +} + +struct rocp_import +{ + rocp_reg_supported_library library_idx = ROCP_REG_LAST; + std::string_view common_name = {}; + std::string_view symbol_name = {}; + std::string_view library_name = {}; +}; + +template +auto rocp_reg_get_imports(std::index_sequence) +{ + auto _data = std::vector{}; + auto _import_scan = [&_data](auto _info) { + if(_info.specialized) + { + _data.emplace_back(rocp_import{ + _info.value, _info.common_name, _info.symbol_name, _info.library_name }); + } + }; + + (_import_scan(supported_library_trait{}), ...); + return _data; +} + +auto +rocp_reg_scan_for_tools() +{ + auto _rocp_reg_lib = common::get_env("ROCPROFILER_REGISTER_LIBRARY", std::string{}); + bool _force_tool = + common::get_env("ROCPROFILER_REGISTER_FORCE_LOAD", !_rocp_reg_lib.empty()); + bool _found_tool = (rocprofiler_configure != nullptr || _force_tool); + + static void* rocprofiler_lib_handle = nullptr; + static rocprofiler_set_api_table_t rocprofiler_lib_config_fn = nullptr; + + if(_force_tool) + { + if(rocprofiler_lib_handle && rocprofiler_lib_config_fn) + return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn); + + if(_rocp_reg_lib.empty()) _rocp_reg_lib = rocprofiler_lib_name; + + auto _rocp_reg_lib_path = fs::path{ _rocp_reg_lib }; + auto _rocp_reg_lib_path_fname = _rocp_reg_lib_path.filename(); + auto _rocp_reg_lib_path_abs = + (_rocp_reg_lib_path.is_absolute()) + ? _rocp_reg_lib_path + : (fs::path{ get_this_library_path() } / _rocp_reg_lib_path_fname); + + // check to see if the rocprofiler library is already loaded + rocprofiler_lib_handle = + dlopen(_rocp_reg_lib_path.c_str(), RTLD_NOLOAD | RTLD_LAZY); + + // try to load with the given path + if(!rocprofiler_lib_handle) + { + rocprofiler_lib_handle = + dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); + } + + // try to load with the absoulte path + if(!rocprofiler_lib_handle) + { + _rocp_reg_lib_path = _rocp_reg_lib_path_abs; + rocprofiler_lib_handle = + dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); + } + + // try to load with the basename path + if(!rocprofiler_lib_handle) + { + _rocp_reg_lib_path = _rocp_reg_lib_path_fname; + rocprofiler_lib_handle = + dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); + } + + if(rocprofiler_register_verbose >= rocprofiler_register_info_level) + ROCPROFILER_REGISTER_INFO << "loaded " << _rocp_reg_lib_path_fname.string() + << " library at " << _rocp_reg_lib_path.string(); + + ROCPROFILER_REGISTER_REQUIRE(rocprofiler_lib_handle) + << _rocp_reg_lib << " failed to load\n"; + + *(void**) (&rocprofiler_lib_config_fn) = + dlsym(rocprofiler_lib_handle, rocprofiler_lib_register_entrypoint); + + ROCPROFILER_REGISTER_REQUIRE(rocprofiler_lib_config_fn) + << _rocp_reg_lib << " did not contain '" + << rocprofiler_lib_register_entrypoint << "' symbol\n"; + } + else if(_found_tool && rocprofiler_set_api_table) + { + rocprofiler_lib_config_fn = &rocprofiler_set_api_table; + } + + return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn); +} + +constexpr auto library_seq = std::make_index_sequence{}; +auto global_mutex = std::recursive_mutex{}; +auto import_info = rocp_reg_get_imports(library_seq); +auto instance_counters = std::array{}; +} // namespace + +extern "C" { +rocprofiler_register_error_code_t +rocprofiler_register_library_api_table( + const char* common_name, + rocprofiler_register_import_func_t import_func, + uint32_t lib_version, + void** api_tables, + uint64_t api_table_length, + rocprofiler_register_library_indentifier_t* register_id) +{ + if(api_table_length < 1) return ROCP_REG_BAD_API_TABLE_LENGTH; + + (void) lib_version; + (void) api_tables; + + auto _lk = std::unique_lock{ global_mutex, std::defer_lock }; + if(_lk.owns_lock()) return ROCP_REG_DEADLOCK; + + auto _scan_result = rocp_reg_scan_for_tools(); + + rocp_import* _import_match = nullptr; + for(auto& itr : import_info) + { + if(itr.common_name == common_name) + { + _import_match = &itr; + break; + } + } + + // not a supported library name + if(!_import_match || _import_match->library_idx == ROCP_REG_LAST) + return ROCP_REG_UNSUPPORTED_API; + + if(import_func != nullptr && + common::get_env("ROCPROFILER_REGISTER_SECURE", false)) + { + auto _import_func_addr = reinterpret_cast(import_func); + auto _segment_addresses = binary::get_segment_addresses(); + auto _in_address_range = [](uintptr_t _addr, + const std::vector& _range) { + for(auto ritr : _range) + { + if(_addr >= ritr.start && _addr < ritr.last) return true; + } + return false; + }; + + // check that the address of the import function is within the expected library + // name + bool _valid_addr = false; + for(const auto& itr : _segment_addresses) + { + if(_in_address_range(_import_func_addr, itr.ranges)) + { + if(std::regex_search(fs::path{ itr.filepath }.filename().string(), + std::regex{ _import_match->library_name.data() })) + { + _valid_addr = true; + } + } + } + + // the library provided + if(!_valid_addr) return ROCP_REG_INVALID_API_ADDRESS; + } + + constexpr auto offset_factor = 64 / std::max(ROCP_REG_LAST, 8); + // if ROCP_REG_LAST > 8, then we can no longer encode 8 instances per lib + // because we ran out of bits (i.e. max of 8 * 8 = 64) + static_assert((offset_factor * ROCP_REG_LAST) <= sizeof(uint64_t) * 8, + "ROCP_REG_LAST has exceeded the max allowable size"); + + // too many instances of the same library + if(instance_counters.at(_import_match->library_idx) >= offset_factor) + return ROCP_REG_EXCESS_API_INSTANCES; + + auto _instance_val = instance_counters.at(_import_match->library_idx)++; + auto& _bits = *reinterpret_cast(®ister_id->handle); + _bits = bitset_t{ (offset_factor * _import_match->library_idx) + _instance_val }; + + if(_bits.to_ulong() != register_id->handle) + throw std::runtime_error("error encoding register_id"); + + // rocprofiler library is dlopened and we have the functor to pass the API data + auto _activate_rocprofiler = (_scan_result.second != nullptr); + + if(_activate_rocprofiler) + { + auto _ret = _scan_result.second( + common_name, lib_version, _instance_val, api_tables, api_table_length); + if(_ret != 0) return ROCP_REG_ROCPROFILER_ERROR; + } + else + { + return ROCP_REG_NO_TOOLS; + } + + return ROCP_REG_SUCCESS; +} + +const char* +rocprofiler_register_error_string(rocprofiler_register_error_code_t _ec) +{ + switch(_ec) + { + case ROCP_REG_SUCCESS: return "rocprofiler_register_success"; + case ROCP_REG_NO_TOOLS: return "rocprofiler_register_no_tools"; + case ROCP_REG_DEADLOCK: return "rocprofiler_register_deadlock"; + case ROCP_REG_BAD_API_TABLE_LENGTH: + return "rocprofiler_register_bad_api_table_length"; + case ROCP_REG_UNSUPPORTED_API: return "rocprofiler_register_unsupported_api"; + case ROCP_REG_INVALID_API_ADDRESS: + return "rocprofiler_register_invalid_api_address"; + case ROCP_REG_ROCPROFILER_ERROR: return "rocprofiler_register_rocprofiler_error"; + case ROCP_REG_EXCESS_API_INSTANCES: + return "rocprofiler_register_excess_api_instances"; + case ROCP_REG_ERROR_CODE_END: return "rocprofiler_register_unknown_error"; + } + return "rocprofiler_register_unknown_error"; +} +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000000..fc1c741ab6 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,465 @@ +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) + +project(rocprofiler-register-tests LANGUAGES C CXX) + +include(CMakeParseArguments) +include(GNUInstallDirs) + +if("${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}") + find_package(rocprofiler-register REQUIRED) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_EXTENSIONS OFF) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_C_VISIBILITY_PRESET "hidden") + set(CMAKE_CXX_VISIBILITY_PRESET "hidden") + set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") + enable_testing() + include(CTest) +endif() + +function(rocp_register_strip_target) + if(CMAKE_BUILD_TYPE MATCHES "(DEBUG|Debug)") + return() + endif() + + cmake_parse_arguments(STRIP "" "" "ARGS" ${ARGN}) + + list(LENGTH STRIP_UNPARSED_ARGUMENTS NUM_UNPARSED) + + if(NUM_UNPARSED EQUAL 1) + set(_TARGET "${STRIP_UNPARSED_ARGUMENTS}") + else() + message( + FATAL_ERROR "rocp_register_strip_target cannot deduce target from \"${ARGN}\"" + ) + endif() + + if(NOT TARGET "${_TARGET}") + message( + FATAL_ERROR + "rocp_register_strip_target not provided valid target: \"${_TARGET}\"") + endif() + + if(CMAKE_STRIP) + add_custom_command( + TARGET ${_TARGET} + POST_BUILD + COMMAND ${CMAKE_STRIP} ${STRIP_ARGS} $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Stripping ${_TARGET}...") + else() + message(WARNING "CMAKE_STRIP not set... Not stripping ${_TARGET}") + endif() +endfunction() + +# +# mock libraries +# +add_subdirectory(hsa-runtime) +add_subdirectory(amdhip) +add_subdirectory(roctx) +add_subdirectory(rocprofiler) + +# +# common to multiple tests +# +find_package(Threads REQUIRED) + +add_library(rocprofiler-register-tests-common INTERFACE) +target_include_directories(rocprofiler-register-tests-common + INTERFACE $) +target_link_libraries(rocprofiler-register-tests-common INTERFACE Threads::Threads stdc++) + +add_library(rocprofiler-register-tests-strong INTERFACE) +target_compile_definitions(rocprofiler-register-tests-strong + INTERFACE ROCP_REG_TEST_WEAK=0) + +add_library(rocprofiler-register-tests-weak INTERFACE) +target_compile_definitions(rocprofiler-register-tests-weak INTERFACE ROCP_REG_TEST_WEAK=1) + +add_library(rocprofiler-register-tests-rocp INTERFACE) +target_link_options(rocprofiler-register-tests-rocp INTERFACE -Wl,--no-as-needed) +target_link_libraries(rocprofiler-register-tests-rocp INTERFACE rocprofiler::rocprofiler) + +add_library(rocprofiler-register::tests-common ALIAS rocprofiler-register-tests-common) +add_library(rocprofiler-register::tests-strong ALIAS rocprofiler-register-tests-strong) +add_library(rocprofiler-register::tests-weak ALIAS rocprofiler-register-tests-weak) +add_library(rocprofiler-register::tests-rocp ALIAS rocprofiler-register-tests-rocp) + +# +# test scenarios +# +function(rocp_register_test_executable _NAME) + set(_SV_ARGS) + foreach(_TYPE "CORE" "PRELOAD" "WRAP" "PRELOAD_WRAP") + list(APPEND _SV_ARGS "${_TYPE}_PASS_REGEX" "${_TYPE}_FAIL_REGEX") + endforeach() + cmake_parse_arguments( + RRTE + "" # options + "SECURE;${_SV_ARGS}" # single value args + "SOURCES;LIBRARIES" # multiple value args + ${ARGN}) + + add_executable(${_NAME}) + target_sources(${_NAME} PRIVATE ${RRTE_SOURCES}) + target_link_libraries(${_NAME} PRIVATE rocprofiler-register::tests-common + ${RRTE_LIBRARIES}) + + function(rocp_register_add_test _TEST_NAME _TARGET _ENV _PASS _FAIL) + if(RRTE_SECURE) + list(APPEND _ENV "ROCPROFILER_REGISTER_SECURE=true") + set(_LABELS "secure") + else() + set(_LABELS "insecure") + endif() + add_test( + NAME ${_TEST_NAME} + COMMAND $ + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + set_tests_properties( + ${_TEST_NAME} + PROPERTIES ENVIRONMENT + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};${_ENV}" + PASS_REGULAR_EXPRESSION + "${_PASS}" + FAIL_REGULAR_EXPRESSION + "${_FAIL}" + LABELS + "${_LABELS}" + ${ARGN}) + endfunction() + + rocp_register_add_test(${_NAME} ${_NAME} "" "${RRTE_CORE_PASS_REGEX}" + "${RRTE_CORE_FAIL_REGEX}") + + rocp_register_add_test(${_NAME}-preload ${_NAME} "LD_PRELOAD=librocprofiler64.so" + "${RRTE_PRELOAD_PASS_REGEX}" "${RRTE_PRELOAD_FAIL_REGEX}") + + rocp_register_add_test(${_NAME}-wrap ${_NAME} "ROCP_REG_TEST_WRAP=1" + "${RRTE_WRAP_PASS_REGEX}" "${RRTE_WRAP_FAIL_REGEX}") + + rocp_register_add_test( + ${_NAME}-preload-wrap ${_NAME} + "LD_PRELOAD=librocprofiler64.so;ROCP_REG_TEST_WRAP=1" + "${RRTE_PRELOAD_WRAP_PASS_REGEX}" "${RRTE_PRELOAD_WRAP_FAIL_REGEX}") + +endfunction() + +# serial +rocp_register_test_executable( + test-amdhip-roctx + SECURE ON + SOURCES test-amdhip-roctx.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip roctx::roctx + CORE_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + WRAP_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + ) + +rocp_register_test_executable( + test-amdhip-roctx-weak + SOURCES test-amdhip-roctx.cpp + LIBRARIES rocprofiler-register::tests-weak + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + ) + +rocp_register_test_executable( + test-amdhip-roctx-rocp + SOURCES test-amdhip-roctx.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip roctx::roctx + rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + ) + +rocp_register_test_executable( + test-amdhip-roctx-weak-rocp + SOURCES test-amdhip-roctx.cpp + LIBRARIES rocprofiler-register::tests-weak rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + ) + +# multithreaded +rocp_register_test_executable( + test-amdhip-roctx-mt + SOURCES test-amdhip-roctx-mt.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip roctx::roctx + CORE_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + WRAP_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n" + ) + +rocp_register_test_executable( + test-amdhip-roctx-mt-weak + SOURCES test-amdhip-roctx-mt.cpp + LIBRARIES rocprofiler-register::tests-weak + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n" + ) + +rocp_register_test_executable( + test-amdhip-roctx-mt-rocp + SOURCES test-amdhip-roctx-mt.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip roctx::roctx + rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n" + ) + +# 29 +rocp_register_test_executable( + test-amdhip-roctx-mt-weak-rocp + SOURCES test-amdhip-roctx-mt.cpp + LIBRARIES rocprofiler-register::tests-weak rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..push. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n.roctx.cpp..pop. thread-[0-3]\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..push. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n.rocprofiler.cpp..pop. thread-[0-3]\n" + ) + +# constructor +rocp_register_test_executable( + test-amdhip-ctor + SOURCES test-amdhip-ctor.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip + CORE_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n" + ) + +rocp_register_test_executable( + test-amdhip-ctor-weak + SOURCES test-amdhip-ctor.cpp + LIBRARIES rocprofiler-register::tests-weak + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n" + ) + +# 41 +rocp_register_test_executable( + test-amdhip-ctor-rocp + SOURCES test-amdhip-ctor.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip + rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n" + ) + +rocp_register_test_executable( + test-amdhip-ctor-weak-rocp + SOURCES test-amdhip-ctor.cpp + LIBRARIES rocprofiler-register::tests-weak rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libhsa-runtime64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n" + ) + +# constructor + mt +rocp_register_test_executable( + test-amdhip-ctor-mt + SOURCES test-amdhip-ctor-mt.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip + CORE_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n" + ) + +rocp_register_test_executable( + test-amdhip-ctor-mt-weak + SOURCES test-amdhip-ctor-mt.cpp + LIBRARIES rocprofiler-register::tests-weak + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.hsa-runtime.cpp. hsa_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n" + ) + +rocp_register_test_executable( + test-amdhip-ctor-mt-rocp + SOURCES test-amdhip-ctor-mt.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip + rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n" + ) + +rocp_register_test_executable( + test-amdhip-ctor-mt-weak-rocp + SOURCES test-amdhip-ctor-mt.cpp + LIBRARIES rocprofiler-register::tests-weak rocprofiler-register::tests-rocp + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n.amdhip.cpp. hip_init\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. hip_init\n" + ) + +add_executable(test-invalid-hsa-runtime) +target_sources(test-invalid-hsa-runtime PRIVATE test-amdhip-roctx.cpp) +target_link_libraries( + test-invalid-hsa-runtime PRIVATE rocprofiler-register::tests-common roctx::roctx + amdhip::amdhip-invalid) + +add_test( + NAME test-secure-invalid-hsa-runtime + COMMAND $ + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + +set_tests_properties( + test-secure-invalid-hsa-runtime + PROPERTIES + ENVIRONMENT + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid:${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_SECURE=1" + LABELS + "secure" + WILL_FAIL + ON) + +add_test( + NAME test-insecure-invalid-hsa-runtime + COMMAND $ + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + +set_tests_properties( + test-insecure-invalid-hsa-runtime + PROPERTIES + ENVIRONMENT + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid:${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_SECURE=0" + LABELS + "insecure") + +add_executable(test-amdhip-hsart-roctx) +target_sources(test-amdhip-hsart-roctx PRIVATE test-amdhip-hsart-roctx.cpp) +target_link_libraries( + test-amdhip-hsart-roctx PRIVATE rocprofiler-register::tests-common + hsa-runtime::hsa-runtime amdhip::amdhip roctx::roctx) + +add_test( + NAME test-force-rocprofiler-dlopen + COMMAND $ + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + +set_tests_properties( + test-force-rocprofiler-dlopen + PROPERTIES + ENVIRONMENT + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_FORCE_LOAD=1;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3" + LABELS + "dlopen;secure") + +add_test( + NAME test-rocprofiler-register-library-base-path + COMMAND $ + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + +set_tests_properties( + test-rocprofiler-register-library-base-path + PROPERTIES + ENVIRONMENT + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=librocprofiler64.so;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" + LABELS + "dlopen;secure") + +add_test( + NAME test-rocprofiler-register-library-absolute-path + COMMAND $ + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + +set_tests_properties( + test-rocprofiler-register-library-absolute-path + PROPERTIES + ENVIRONMENT + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/librocprofiler64.so;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" + LABELS + "dlopen;secure") diff --git a/tests/amdhip/CMakeLists.txt b/tests/amdhip/CMakeLists.txt new file mode 100644 index 0000000000..0e667af2fe --- /dev/null +++ b/tests/amdhip/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# +# + +if(NOT TARGET rocprofiler-register::rocprofiler-register) + find_package(rocprofiler-register REQUIRED) +endif() + +add_library(amdhip SHARED) +add_library(amdhip::amdhip ALIAS amdhip) +target_sources(amdhip PRIVATE amdhip.cpp amdhip.hpp) +target_include_directories(amdhip PUBLIC $) +target_link_libraries( + amdhip + PRIVATE rocprofiler-register::rocprofiler-register + PUBLIC hsa-runtime::hsa-runtime) +set_target_properties( + amdhip + PROPERTIES OUTPUT_NAME amdhip64 + SOVERSION 6 + VERSION 6.0.1) +rocp_register_strip_target(amdhip) + +add_library(amdhip-invalid SHARED) +add_library(amdhip::amdhip-invalid ALIAS amdhip-invalid) +target_sources(amdhip-invalid PRIVATE amdhip.cpp amdhip.hpp) +target_include_directories(amdhip-invalid + PUBLIC $) +target_link_libraries( + amdhip-invalid + PRIVATE rocprofiler-register::rocprofiler-register + PUBLIC hsa-runtime::hsa-runtime-invalid) +set_target_properties( + amdhip-invalid + PROPERTIES OUTPUT_NAME amdhip64 + SOVERSION 6 + VERSION 6.0.1 + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid") +rocp_register_strip_target(amdhip-invalid) diff --git a/tests/amdhip/amdhip.cpp b/tests/amdhip/amdhip.cpp new file mode 100644 index 0000000000..02208d4d17 --- /dev/null +++ b/tests/amdhip/amdhip.cpp @@ -0,0 +1,154 @@ +#include "amdhip.hpp" +#include "hsa-runtime.hpp" + +#include + +#include +#include +#include +#include + +#define ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \ + HIP_VERSION_MAJOR, HIP_VERSION_MINOR, HIP_VERSION_PATCH) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(hip, ROCP_REG_VERSION) + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace hip +{ +namespace +{ +auto& +get_hip_api_table_impl() +{ + static auto _table = std::atomic{ nullptr }; + return _table; +} + +void +register_profiler_impl() +{ + static auto _const_api_table = HipApiTable{}; + initialize_hip_api_table(&_const_api_table); + + // set this before any recursive opportunity arises + get_hip_api_table_impl().exchange(&_const_api_table); + + // create a copy of the api table for modification by registration + static auto _profiler_api_table = HipApiTable{}; + copy_hip_api_table(&_profiler_api_table, &_const_api_table); + + void* _profiler_api_table_v = static_cast(&_profiler_api_table); + + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto success = + rocprofiler_register_library_api_table("hip", + &ROCPROFILER_REGISTER_IMPORT_FUNC(hip), + ROCP_REG_VERSION, + &_profiler_api_table_v, + 1, + &lib_id); + + if(success == ROCP_REG_SUCCESS) + { + printf("[%s] hip identifier %lu\n", ROCP_REG_FILE_NAME, lib_id.handle); + auto* _api_table = &_const_api_table; + if(!get_hip_api_table_impl().compare_exchange_strong(_api_table, + &_profiler_api_table)) + { + // with the current impl, if we ever get here, someone is calling one the + // functions in this anonymous namespace that shouldn't + std::cerr + << "register_profiler_impl expected the API table to be the internal " + "implementation and yet it is not. something went wrong.\n"; + abort(); + } + } + else if(success != ROCP_REG_NO_TOOLS) + { + std::cerr << "HIP library failed to register with rocprofiler-register: " + << rocprofiler_register_error_string(success) << "\n"; + exit(EXIT_FAILURE); + } +} + +void +register_profiler() +{ + // this registration scheme is designed to minimize overhead once + // registered (only pay cost of checking atomic boolean) + // once the profiler is registered. If the library has not + // been registered and two or more threads try to register concurrently + // the first thread to acquire the lock below, will block the + // threads until registration is complete. However, + // if the same thread performing the registration re-enters this function + // i.e. this library's API is called during registration, this function + // will prevent a deadlock by not attempting to re-enter the + // the call-once and not releasing any waiting threads by flipping + // the _is_registered field to true. + static auto _is_registered = std::atomic{ false }; + + if(!_is_registered.load(std::memory_order_acquire)) + { + using mutex_t = std::recursive_mutex; + using auto_lock_t = std::unique_lock; + static auto _once = std::once_flag{}; + static auto _mutex = mutex_t{}; + + // defer the lock so we can check for recursion + auto _lk = auto_lock_t{ _mutex, std::defer_lock }; + + // this will be true if the same thread currently executing the call_once invokes + // the library's API while registering the profiler (e.g. tool which wants to + // instrument HIP API invokes a HIP function while registering with the profiler) + // we allow this thread to proceed and access the "const" API table but + // return so it does not flip _is_registered to true, which would result + // in any subsequent threads not waiting until the library is fully registered, + // resulting in missed callbacks for the tools + if(_lk.owns_lock()) return; + + // ensures any subsequent threads wait until the first thread + // finishes registration + _lk.lock(); + // call_once to ensure that we only register once + std::call_once(_once, register_profiler_impl); + // the first thread has completed registration and all + // threads waiting on lock will be released and this + // block will not be entered again + _is_registered.exchange(true, std::memory_order_release); + } +} +} // namespace + +HipApiTable* +get_hip_api_table() +{ + static auto _once = std::once_flag{}; + std::call_once(_once, hsa_init); + register_profiler(); + return get_hip_api_table_impl().load(std::memory_order_relaxed); +} + +void +hip_init() +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} + +bool _constructed = true; +} // namespace hip + +extern "C" { +void +hip_init(void) +{ + if(hip::_constructed) hip::get_hip_api_table()->hip_init_fn(); +} +} diff --git a/tests/amdhip/amdhip.hpp b/tests/amdhip/amdhip.hpp new file mode 100644 index 0000000000..bdfebdf857 --- /dev/null +++ b/tests/amdhip/amdhip.hpp @@ -0,0 +1,40 @@ +#pragma once + +#define HIP_VERSION_MAJOR 6 +#define HIP_VERSION_MINOR 0 +#define HIP_VERSION_PATCH 1 + +#include + +extern "C" { +// fake hip function +void +hip_init(void) __attribute__((visibility("default"))); +} + +namespace hip +{ +struct HipApiTable +{ + uint64_t size = 0; + decltype(::hip_init)* hip_init_fn = nullptr; +}; + +void +hip_init(); + +// populates hip api table with function pointers +inline void +initialize_hip_api_table(HipApiTable* dst) +{ + dst->size = sizeof(HipApiTable); + dst->hip_init_fn = &::hip::hip_init; +} + +// copies the api table from src to dst +inline void +copy_hip_api_table(HipApiTable* dst, const HipApiTable* src) +{ + *dst = *src; +} +} // namespace hip diff --git a/tests/common/fwd.h b/tests/common/fwd.h new file mode 100644 index 0000000000..571c66c0d4 --- /dev/null +++ b/tests/common/fwd.h @@ -0,0 +1,31 @@ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(ROCP_REG_TEST_WEAK) && ROCP_REG_TEST_WEAK > 0 +# pragma weak hip_init +# pragma weak hsa_init +# pragma weak roctxRangePush +# pragma weak roctxRangePop +#endif + +extern void +hip_init(void); + +extern void +hsa_init(void); + +extern void +roctxRangePush(const char*); + +extern void +roctxRangePop(const char*); + +#ifdef __cplusplus +} +#endif diff --git a/tests/common/fwd.hpp b/tests/common/fwd.hpp new file mode 100644 index 0000000000..6438a2a77b --- /dev/null +++ b/tests/common/fwd.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include "fwd.h" + +#include +#include +#include +#include + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace +{ +decltype(hip_init)* hip_init_fn = nullptr; +decltype(hsa_init)* hsa_init_fn = nullptr; +decltype(roctxRangePush)* roctxRangePush_fn = nullptr; +decltype(roctxRangePush)* roctxRangePop_fn = nullptr; + +enum rocp_reg_test_modes : uint8_t +{ + ROCP_REG_TEST_NONE = 0x0, + ROCP_REG_TEST_HIP = (1 << 0), + ROCP_REG_TEST_HSA = (1 << 1), + ROCP_REG_TEST_ROCTX = (1 << 2), +}; + +template +inline void +resolve_symbols(int _open_mode = RTLD_LOCAL | RTLD_LAZY) +{ + auto* _open_mode_env = std::getenv("ROCP_REG_TEST_OPEN_MODE"); + if(_open_mode_env) + { + constexpr auto npos = std::string_view::npos; + auto _open_mode_v = std::string_view{ _open_mode_env }; + if(_open_mode_v.find("RTLD_GLOBAL") != npos) + _open_mode = RTLD_GLOBAL; + else if(_open_mode_v.find("RTLD_NOLOAD") != npos) + _open_mode = RTLD_NOLOAD; + else + _open_mode = RTLD_LOCAL; + + if(_open_mode_v.find("RTLD_NOW") != npos) + _open_mode |= RTLD_NOW; + else + _open_mode |= RTLD_LAZY; + } + + auto _resolve_dlopen = [_open_mode](void*& _handle, const char* _lib_name) { + fprintf( + stderr, "[%s] dlopen %s, %i\n", ROCP_REG_FILE_NAME, _lib_name, _open_mode); + _handle = dlopen(_lib_name, _open_mode); + if(!_handle) + { + fprintf(stderr, "Failure opening '%s'\n", _lib_name); + exit(EXIT_FAILURE); + } + }; + + auto _resolve_dlsym = [](auto& _func, void* _handle, const char* _func_name) { + if(!_func && _handle && _func_name) + { + auto* _func_v = dlsym(_handle, _func_name); + if(_func_v) *(void**) (&_func) = _func_v; + } + }; + + void* amdhip_handle = nullptr; + void* hsart_handle = nullptr; + void* roctx_handle = nullptr; + + if constexpr((Idx & ROCP_REG_TEST_HIP) == ROCP_REG_TEST_HIP) + { + hip_init_fn = hip_init; + if(!hip_init_fn) _resolve_dlopen(amdhip_handle, "libamdhip64.so"); + _resolve_dlsym(hip_init_fn, amdhip_handle, "hip_init"); + } + + if constexpr((Idx & ROCP_REG_TEST_HSA) == ROCP_REG_TEST_HSA) + { + hsa_init_fn = hsa_init; + if(!hsa_init_fn) _resolve_dlopen(hsart_handle, "libhsa-runtime64.so"); + _resolve_dlsym(hsa_init_fn, hsart_handle, "hsa_init"); + } + + if constexpr((Idx & ROCP_REG_TEST_ROCTX) == ROCP_REG_TEST_ROCTX) + { + roctxRangePush_fn = roctxRangePush; + roctxRangePop_fn = roctxRangePop; + if(!roctxRangePush_fn || !roctxRangePop_fn) + _resolve_dlopen(roctx_handle, "libroctx64.so"); + _resolve_dlsym(roctxRangePush_fn, roctx_handle, "roctxRangePush"); + _resolve_dlsym(roctxRangePop_fn, roctx_handle, "roctxRangePop"); + } +} +} // namespace diff --git a/tests/hsa-runtime/CMakeLists.txt b/tests/hsa-runtime/CMakeLists.txt new file mode 100644 index 0000000000..5408ea9637 --- /dev/null +++ b/tests/hsa-runtime/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# +# + +if(NOT TARGET rocprofiler-register::rocprofiler-register) + # find_package(rocprofiler-register REQUIRED) +endif() + +add_library(hsa-runtime SHARED) +add_library(hsa-runtime::hsa-runtime ALIAS hsa-runtime) +target_sources(hsa-runtime PRIVATE hsa-runtime.cpp hsa-runtime.hpp) +target_include_directories(hsa-runtime + PUBLIC $) +target_link_libraries(hsa-runtime PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + hsa-runtime + PROPERTIES OUTPUT_NAME hsa-runtime64 + SOVERSION 2 + VERSION 2.1.0) +rocp_register_strip_target(hsa-runtime) + +add_library(hsa-runtime-invalid SHARED) +add_library(hsa-runtime::hsa-runtime-invalid ALIAS hsa-runtime-invalid) +target_sources(hsa-runtime-invalid PRIVATE hsa-runtime.cpp hsa-runtime.hpp) +target_include_directories(hsa-runtime-invalid + PUBLIC $) +target_link_libraries(hsa-runtime-invalid + PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + hsa-runtime-invalid + PROPERTIES OUTPUT_NAME hsa-runtime64 + SOVERSION 1 + VERSION 1.2.3 + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid) +rocp_register_strip_target(hsa-runtime-invalid) diff --git a/tests/hsa-runtime/hsa-runtime.cpp b/tests/hsa-runtime/hsa-runtime.cpp new file mode 100644 index 0000000000..90a1433594 --- /dev/null +++ b/tests/hsa-runtime/hsa-runtime.cpp @@ -0,0 +1,149 @@ +#include "hsa-runtime.hpp" + +#include + +#include +#include +#include +#include + +#define ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \ + HSA_VERSION_MAJOR, HSA_VERSION_MINOR, HSA_VERSION_PATCH) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(hsa, ROCP_REG_VERSION) + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace hsa +{ +namespace +{ +auto& +get_hsa_api_table_impl() +{ + static auto _table = std::atomic{ nullptr }; + return _table; +} + +void +register_profiler_impl() +{ + static auto _const_api_table = HsaApiTable{}; + initialize_hsa_api_table(&_const_api_table); + + // set this before any recursive opportunity arises + get_hsa_api_table_impl().exchange(&_const_api_table); + + // create a copy of the api table for modification by registration + static auto _profiler_api_table = HsaApiTable{}; + copy_hsa_api_table(&_profiler_api_table, &_const_api_table); + + void* _profiler_api_table_v = static_cast(&_profiler_api_table); + + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto success = + rocprofiler_register_library_api_table("hsa", + &ROCPROFILER_REGISTER_IMPORT_FUNC(hsa), + ROCP_REG_VERSION, + &_profiler_api_table_v, + 1, + &lib_id); + + if(success == 0) + { + printf("[%s] hsa identifier %lu\n", ROCP_REG_FILE_NAME, lib_id.handle); + auto* _api_table = &_const_api_table; + if(!get_hsa_api_table_impl().compare_exchange_strong(_api_table, + &_profiler_api_table)) + { + // with the current impl, if we ever get here, someone is calling one the + // functions in this anonymous namespace that shouldn't + std::cerr + << "register_profiler_impl expected the API table to be the internal " + "implementation and yet it is not. something went wrong.\n"; + abort(); + } + } + else if(success != ROCP_REG_NO_TOOLS) + { + std::cerr << "HSA library failed to register with rocprofiler-register: " + << rocprofiler_register_error_string(success) << "\n"; + exit(EXIT_FAILURE); + } +} + +void +register_profiler() +{ + // this registration scheme is designed to minimize overhead once + // registered (only pay cost of checking atomic boolean) + // once the profiler is registered. If the library has not + // been registered and two or more threads try to register concurrently + // the first thread to acquire the lock below, will block the + // threads until registration is complete. However, + // if the same thread performing the registration re-enters this function + // i.e. this library's API is called during registration, this function + // will prevent a deadlock by not attempting to re-enter the + // the call-once and not releasing any waiting threads by flipping + // the _is_registered field to true. + static auto _is_registered = std::atomic{ false }; + + if(!_is_registered.load(std::memory_order_acquire)) + { + using mutex_t = std::recursive_mutex; + using auto_lock_t = std::unique_lock; + static auto _once = std::once_flag{}; + static auto _mutex = mutex_t{}; + + // defer the lock so we can check for recursion + auto _lk = auto_lock_t{ _mutex, std::defer_lock }; + + // this will be true if the same thread currently executing the call_once invokes + // the library's API while registering the profiler (e.g. tool which wants to + // instrument HSA API invokes a HSA function while registering with the profiler) + // we allow this thread to proceed and access the "const" API table but + // return so it does not flip _is_registered to true, which would result + // in any subsequent threads not waiting until the library is fully registered, + // resulting in missed callbacks for the tools + if(_lk.owns_lock()) return; + + // ensures any subsequent threads wait until the first thread + // finishes registration + _lk.lock(); + // call_once to ensure that we only register once + std::call_once(_once, register_profiler_impl); + // the first thread has completed registration and all + // threads waiting on lock will be released and this + // block will not be entered again + _is_registered.exchange(true, std::memory_order_release); + } +} +} // namespace + +HsaApiTable* +get_hsa_api_table() +{ + register_profiler(); + return get_hsa_api_table_impl().load(std::memory_order_relaxed); +} + +void +hsa_init() +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} +} // namespace hsa + +extern "C" { +void +hsa_init(void) +{ + hsa::get_hsa_api_table()->hsa_init_fn(); +} +} diff --git a/tests/hsa-runtime/hsa-runtime.hpp b/tests/hsa-runtime/hsa-runtime.hpp new file mode 100644 index 0000000000..5dbc9c942a --- /dev/null +++ b/tests/hsa-runtime/hsa-runtime.hpp @@ -0,0 +1,40 @@ +#pragma once + +#define HSA_VERSION_MAJOR 2 +#define HSA_VERSION_MINOR 1 +#define HSA_VERSION_PATCH 0 + +#include + +extern "C" { +// fake hsa function +void +hsa_init(void) __attribute__((visibility("default"))); +} + +namespace hsa +{ +struct HsaApiTable +{ + uint64_t size = 0; + decltype(::hsa_init)* hsa_init_fn = nullptr; +}; + +void +hsa_init(); + +// populates hsa api table with function pointers +inline void +initialize_hsa_api_table(HsaApiTable* dst) +{ + dst->size = sizeof(HsaApiTable); + dst->hsa_init_fn = &::hsa::hsa_init; +} + +// copies the api table from src to dst +inline void +copy_hsa_api_table(HsaApiTable* dst, const HsaApiTable* src) +{ + *dst = *src; +} +} // namespace hsa diff --git a/tests/rocprofiler/CMakeLists.txt b/tests/rocprofiler/CMakeLists.txt new file mode 100644 index 0000000000..3fd75325c2 --- /dev/null +++ b/tests/rocprofiler/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# mock rocprofiler library +# +add_library(rocprofiler SHARED) +add_library(rocprofiler::rocprofiler ALIAS rocprofiler) +target_sources(rocprofiler PRIVATE rocprofiler.cpp) +target_include_directories(rocprofiler PUBLIC $ + $) +set_target_properties( + rocprofiler + PROPERTIES OUTPUT_NAME rocprofiler64 + SOVERSION 2 + VERSION 2.0.0) +rocp_register_strip_target(rocprofiler) diff --git a/tests/rocprofiler/rocprofiler.cpp b/tests/rocprofiler/rocprofiler.cpp new file mode 100644 index 0000000000..9b26feb342 --- /dev/null +++ b/tests/rocprofiler/rocprofiler.cpp @@ -0,0 +1,135 @@ + +#include +#include +#include + +#include +#include +#include + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace rocprofiler +{ +void +hip_init() +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} + +void +hsa_init() +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} + +void +roctx_range_push(const char* name) +{ + printf("[%s][push] %s\n", ROCP_REG_FILE_NAME, name); +} + +void +roctx_range_pop(const char* name) +{ + printf("[%s][pop] %s\n", ROCP_REG_FILE_NAME, name); +} +} // namespace rocprofiler + +extern "C" { +struct rocprofiler_configure_result_t +{ + int (*initialize)(void*) = nullptr; + int (*finalize)(void*) = nullptr; + void* data = nullptr; +}; + +rocprofiler_configure_result_t* +rocprofiler_configure(uint32_t, const char*, uint32_t, uint32_t) + __attribute__((visibility("default"))); + +int +rocprofiler_set_api_table(const char*, uint64_t, uint64_t, void**, uint64_t) + __attribute__((visibility("default"))); + +rocprofiler_configure_result_t* +rocprofiler_configure(uint32_t version, + const char* runtime_version, + uint32_t priority, + uint32_t tool_id) +{ + (void) version; + (void) runtime_version; + (void) priority; + (void) tool_id; + + return nullptr; +} + +int +rocprofiler_set_api_table(const char* name, + uint64_t lib_version, + uint64_t lib_instance, + void** tables, + uint64_t num_tables) +{ + printf("[%s] %s :: %lu :: %lu :: %lu\n", + ROCP_REG_FILE_NAME, + name, + lib_version, + lib_instance, + num_tables); + + using hip_table_t = hip::HipApiTable; + using hsa_table_t = hsa::HsaApiTable; + using roctx_table_t = roctx::ROCTxApiTable; + + auto* _wrap_v = std::getenv("ROCP_REG_TEST_WRAP"); + bool _wrap = (_wrap_v != nullptr && std::stoi(_wrap_v) != 0); + + if(_wrap) + { + if(num_tables != 1) + throw std::runtime_error{ std::string{ "unexpected number of tables: " } + + std::to_string(num_tables) }; + + if(tables == nullptr) throw std::runtime_error{ "nullptr to tables" }; + if(tables[0] == nullptr) throw std::runtime_error{ "nullptr to tables[0]" }; + + if(std::string_view{ name } == "hip") + { + hip_table_t* _table = static_cast(tables[0]); + _table->hip_init_fn = &rocprofiler::hip_init; + } + else if(std::string_view{ name } == "hsa") + { + hsa_table_t* _table = static_cast(tables[0]); + _table->hsa_init_fn = &rocprofiler::hsa_init; + } + else if(std::string_view{ name } == "roctx") + { + roctx_table_t* _table = static_cast(tables[0]); + _table->roctxRangePush_fn = &rocprofiler::roctx_range_push; + _table->roctxRangePop_fn = &rocprofiler::roctx_range_pop; + } + } + + return 0; +} +} + +void + rocp_ctor(void) __attribute__((constructor)); +bool rocprofiler_test_lib_link = false; + +void +rocp_ctor() +{ + rocprofiler_test_lib_link = true; + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} diff --git a/tests/roctx/CMakeLists.txt b/tests/roctx/CMakeLists.txt new file mode 100644 index 0000000000..05f9f5bac1 --- /dev/null +++ b/tests/roctx/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# +# + +if(NOT TARGET rocprofiler-register::rocprofiler-register) + find_package(rocprofiler-register REQUIRED) +endif() + +add_library(roctx SHARED) +add_library(roctx::roctx ALIAS roctx) +target_sources(roctx PRIVATE roctx.cpp roctx.hpp) +target_include_directories(roctx PUBLIC $) +target_link_libraries(roctx PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + roctx + PROPERTIES OUTPUT_NAME roctx64 + SOVERSION 4 + VERSION 4.6.1) +rocp_register_strip_target(roctx) diff --git a/tests/roctx/roctx.cpp b/tests/roctx/roctx.cpp new file mode 100644 index 0000000000..4d428a67ca --- /dev/null +++ b/tests/roctx/roctx.cpp @@ -0,0 +1,170 @@ +#ifdef NDEBUG +# undef NDEBUG +#endif + +#include "roctx.hpp" + +#include + +#include +#include +#include +#include +#include + +#define ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \ + ROCTX_VERSION_MAJOR, ROCTX_VERSION_MINOR, ROCTX_VERSION_PATCH) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(roctx, ROCP_REG_VERSION) + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace roctx +{ +namespace +{ +auto& +get_roctx_api_table_impl() +{ + static auto _table = std::atomic{ nullptr }; + return _table; +} + +void +register_profiler_impl() +{ + static auto _const_api_table = ROCTxApiTable{}; + initialize_roctx_api_table(&_const_api_table); + + // set this before any recursive opportunity arises + get_roctx_api_table_impl().exchange(&_const_api_table); + + // create a copy of the api table for modification by registration + static auto _profiler_api_table = ROCTxApiTable{}; + copy_roctx_api_table(&_profiler_api_table, &_const_api_table); + + void* _profiler_api_table_v = static_cast(&_profiler_api_table); + + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto success = + rocprofiler_register_library_api_table("roctx", + &ROCPROFILER_REGISTER_IMPORT_FUNC(roctx), + ROCP_REG_VERSION, + &_profiler_api_table_v, + 1, + &lib_id); + + if(success == 0) + { + printf("[%s] roctx identifier %lu\n", ROCP_REG_FILE_NAME, lib_id.handle); + auto* _api_table = &_const_api_table; + if(!get_roctx_api_table_impl().compare_exchange_strong(_api_table, + &_profiler_api_table)) + { + // with the current impl, if we ever get here, someone is calling one the + // functions in this anonymous namespace that shouldn't + std::cerr + << "register_profiler_impl expected the API table to be the internal " + "implementation and yet it is not. something went wrong.\n"; + abort(); + } + } + else if(success != ROCP_REG_NO_TOOLS) + { + std::cerr << "ROCTx library failed to register with rocprofiler-register: " + << rocprofiler_register_error_string(success) << "\n"; + exit(EXIT_FAILURE); + } +} + +void +register_profiler() +{ + // this registration scheme is designed to minimize overhead once + // registered (only pay cost of checking atomic boolean) + // once the profiler is registered. If the library has not + // been registered and two or more threads try to register concurrently + // the first thread to acquire the lock below, will block the + // threads until registration is complete. However, + // if the same thread performing the registration re-enters this function + // i.e. this library's API is called during registration, this function + // will prevent a deadlock by not attempting to re-enter the + // the call-once and not releasing any waiting threads by flipping + // the _is_registered field to true. + static auto _is_registered = std::atomic{ false }; + + if(!_is_registered.load(std::memory_order_acquire)) + { + using mutex_t = std::recursive_mutex; + using auto_lock_t = std::unique_lock; + static auto _once = std::once_flag{}; + static auto _mutex = mutex_t{}; + + // defer the lock so we can check for recursion + auto _lk = auto_lock_t{ _mutex, std::defer_lock }; + + // this will be true if the same thread currently executing the call_once invokes + // the library's API while registering the profiler (e.g. tool which wants to + // instrument ROCTX API invokes a ROCTX function while registering with the + // profiler) we allow this thread to proceed and access the "const" API table but + // return so it does not flip _is_registered to true, which would result + // in any subsequent threads not waiting until the library is fully registered, + // resulting in missed callbacks for the tools + if(_lk.owns_lock()) return; + + // ensures any subsequent threads wait until the first thread + // finishes registration + _lk.lock(); + // call_once to ensure that we only register once + std::call_once(_once, register_profiler_impl); + // the first thread has completed registration and all + // threads waiting on lock will be released and this + // block will not be entered again + _is_registered.exchange(true, std::memory_order_release); + } +} +} // namespace + +ROCTxApiTable* +get_roctx_api_table() +{ + register_profiler(); + return get_roctx_api_table_impl().load(std::memory_order_relaxed); +} + +void +roctx_range_push(const char* name) +{ + printf("[%s][push] %s\n", ROCP_REG_FILE_NAME, name); +} + +void +roctx_range_pop(const char* name) +{ + printf("[%s][pop] %s\n", ROCP_REG_FILE_NAME, name); +} +} // namespace roctx + +extern "C" { +void +roctxRangePush(const char* name) +{ + auto&& _func = roctx::get_roctx_api_table()->roctxRangePush_fn; + assert(_func != nullptr); + _func(name); +} + +void +roctxRangePop(const char* name) +{ + auto&& _func = roctx::get_roctx_api_table()->roctxRangePop_fn; + if(_func == nullptr) throw std::runtime_error("nullptr"); + _func(name); +} +} diff --git a/tests/roctx/roctx.hpp b/tests/roctx/roctx.hpp new file mode 100644 index 0000000000..ce2ae3ec99 --- /dev/null +++ b/tests/roctx/roctx.hpp @@ -0,0 +1,46 @@ +#pragma once + +#define ROCTX_VERSION_MAJOR 4 +#define ROCTX_VERSION_MINOR 6 +#define ROCTX_VERSION_PATCH 1 + +#include + +extern "C" { +void +roctxRangePush(const char*) __attribute__((visibility("default"))); +void +roctxRangePop(const char*) __attribute__((visibility("default"))); +} + +namespace roctx +{ +struct ROCTxApiTable +{ + uint64_t size = 0; + decltype(::roctxRangePush)* roctxRangePush_fn = nullptr; + decltype(::roctxRangePop)* roctxRangePop_fn = nullptr; +}; + +void +roctx_range_push(const char*); + +void +roctx_range_pop(const char*); + +// populates roctx api table with function pointers +inline void +initialize_roctx_api_table(ROCTxApiTable* dst) +{ + dst->size = sizeof(ROCTxApiTable); + dst->roctxRangePush_fn = &::roctx::roctx_range_push; + dst->roctxRangePop_fn = &::roctx::roctx_range_pop; +} + +// copies the api table from src to dst +inline void +copy_roctx_api_table(ROCTxApiTable* dst, const ROCTxApiTable* src) +{ + *dst = *src; +} +} // namespace roctx diff --git a/tests/start-up-test/CMakeLists.txt b/tests/start-up-test/CMakeLists.txt new file mode 100644 index 0000000000..407eb4e3cc --- /dev/null +++ b/tests/start-up-test/CMakeLists.txt @@ -0,0 +1,3 @@ +# +# +# diff --git a/tests/test-amdhip-ctor-mt.cpp b/tests/test-amdhip-ctor-mt.cpp new file mode 100644 index 0000000000..60190a0bd5 --- /dev/null +++ b/tests/test-amdhip-ctor-mt.cpp @@ -0,0 +1,72 @@ + +#include +#include +#include +#include +#include +#include + +#include "common/fwd.hpp" + +void +run(const std::string& name, pthread_barrier_t* _barrier) +{ + if(_barrier) pthread_barrier_wait(_barrier); + + if(hsa_init_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + hsa_init_fn(); + } + + if(hip_init_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + hip_init_fn(); + } + + if(roctxRangePush_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + roctxRangePush_fn(name.c_str()); + } + + if(roctxRangePop_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + roctxRangePop_fn(name.c_str()); + } +} + +auto +run_threads(unsigned long n) +{ + resolve_symbols(); + + auto threads = std::vector{}; + auto names = std::vector{}; + + for(unsigned long i = 0; i < n; ++i) + names.emplace_back(std::string{ "thread-" } + std::to_string(i)); + + auto _barrier = pthread_barrier_t{}; + pthread_barrier_init(&_barrier, nullptr, n); + + for(unsigned long i = 0; i < n; ++i) + threads.emplace_back(run, names.at(i), &_barrier); + + for(auto& itr : threads) + itr.join(); + + pthread_barrier_destroy(&_barrier); + + return n; +} + +auto run_n = run_threads(4); + +int +main() +{ + return (run_n == 4) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/test-amdhip-ctor.cpp b/tests/test-amdhip-ctor.cpp new file mode 100644 index 0000000000..64fd53c9d1 --- /dev/null +++ b/tests/test-amdhip-ctor.cpp @@ -0,0 +1,42 @@ + +#include +#include +#include + +#include "common/fwd.hpp" + +std::string +run(const std::string& name) +{ + resolve_symbols(); + + if(hsa_init_fn) + { + hsa_init_fn(); + } + + if(hip_init_fn) + { + hip_init_fn(); + } + + if(roctxRangePush_fn) + { + roctxRangePush_fn(name.c_str()); + } + + if(roctxRangePop_fn) + { + roctxRangePop_fn(name.c_str()); + } + + return name; +} + +auto run_name = run("thread-ctor"); + +int +main() +{ + return (run_name == "thread-ctor") ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/test-amdhip-hsart-roctx.cpp b/tests/test-amdhip-hsart-roctx.cpp new file mode 100644 index 0000000000..7e4e34f4e3 --- /dev/null +++ b/tests/test-amdhip-hsart-roctx.cpp @@ -0,0 +1,43 @@ + +#include +#include + +#include "common/fwd.hpp" + +void +run(const std::string& name) +{ + if(hip_init_fn) + { + hip_init_fn(); + } + + if(hsa_init_fn) + { + hsa_init_fn(); + } + + if(roctxRangePush_fn) + { + roctxRangePush_fn(name.c_str()); + } + + if(roctxRangePop_fn) + { + roctxRangePop_fn(name.c_str()); + } +} + +int +main(int argc, char** argv) +{ + unsigned long n = 1; + if(argc > 1) n = std::stoul(argv[1]); + + resolve_symbols(); + + for(unsigned long i = 0; i < n; ++i) + run("thread-main"); + + return 0; +} diff --git a/tests/test-amdhip-roctx-mt.cpp b/tests/test-amdhip-roctx-mt.cpp new file mode 100644 index 0000000000..49f8a32056 --- /dev/null +++ b/tests/test-amdhip-roctx-mt.cpp @@ -0,0 +1,72 @@ + +#include +#include +#include +#include +#include + +#include "common/fwd.hpp" + +void +run(const std::string& name, pthread_barrier_t* _barrier) +{ + if(_barrier) pthread_barrier_wait(_barrier); + + if(hip_init_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + hip_init_fn(); + } + + if(hsa_init_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + hsa_init_fn(); + } + + if(roctxRangePush_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + roctxRangePush_fn(name.c_str()); + } + + if(roctxRangePop_fn) + { + if(_barrier) pthread_barrier_wait(_barrier); + roctxRangePop_fn(name.c_str()); + } +} + +void +run_threads(unsigned long n) +{ + auto threads = std::vector{}; + auto names = std::vector{}; + + for(unsigned long i = 0; i < n; ++i) + names.emplace_back(std::string{ "thread-" } + std::to_string(i)); + + auto _barrier = pthread_barrier_t{}; + pthread_barrier_init(&_barrier, nullptr, n); + + for(unsigned long i = 0; i < n; ++i) + threads.emplace_back(run, names.at(i), &_barrier); + + for(auto& itr : threads) + itr.join(); + + pthread_barrier_destroy(&_barrier); +} + +int +main(int argc, char** argv) +{ + unsigned long n = 4; + if(argc > 1) n = std::stoul(argv[1]); + + resolve_symbols(); + + run_threads(n); + + return 0; +} diff --git a/tests/test-amdhip-roctx.cpp b/tests/test-amdhip-roctx.cpp new file mode 100644 index 0000000000..142480a9c7 --- /dev/null +++ b/tests/test-amdhip-roctx.cpp @@ -0,0 +1,43 @@ + +#include +#include + +#include "common/fwd.hpp" + +void +run(const std::string& name) +{ + if(hip_init_fn) + { + hip_init_fn(); + } + + if(hsa_init_fn) + { + hsa_init_fn(); + } + + if(roctxRangePush_fn) + { + roctxRangePush_fn(name.c_str()); + } + + if(roctxRangePop_fn) + { + roctxRangePop_fn(name.c_str()); + } +} + +int +main(int argc, char** argv) +{ + unsigned long n = 1; + if(argc > 1) n = std::stoul(argv[1]); + + resolve_symbols(); + + for(unsigned long i = 0; i < n; ++i) + run("thread-main"); + + return 0; +} From 33b19051d2576596b25c78ee1eee8144ed4898e3 Mon Sep 17 00:00:00 2001 From: Benjamin Welton Date: Thu, 17 Aug 2023 18:01:34 -0700 Subject: [PATCH 03/49] Added submodules for glog/fmt (#9) * Added submodules for glog/fmt Removes existing printing/formatting code. * Update external/CMakeLists.txt Co-authored-by: Jonathan R. Madsen * Update external/CMakeLists.txt Co-authored-by: Jonathan R. Madsen * Update external/CMakeLists.txt - checkout submodule if not already checked out or clone repo if no .gitmodules file - find_package(... REQUIRED) * Disable tests from external directory * Update external/CMakeLists.txt - fix type: BRANCH -> REPO_BRANCH * Update cmake/rocprofiler_register_formatting.cmake - Include external/CMakeLists.txt in format-cmake target - include format-cmake in format target * Fix cmake options - ROCPROFILE_REGISTER_* -> ROCPROFILER_REGISTER_* * Update rocprofiler_register_linting.cmake - fix header filter to exclude external headers - enable warning-as-errors except for misc-header-include-cycle because that originates in fmt headers * Fix clang-tidy error in utility.cpp - a bit out of place in this PR but caught due to --warning-as-errors addition --------- Co-authored-by: Jonathan R. Madsen --- .gitmodules | 6 + CMakeLists.txt | 1 + cmake/rocprofiler_register_formatting.cmake | 5 +- cmake/rocprofiler_register_linting.cmake | 6 +- cmake/rocprofiler_register_options.cmake | 2 + external/CMakeLists.txt | 33 ++ external/fmt | 1 + external/glog | 1 + scripts/run-ci.py | 2 +- .../lib/rocprofiler-register/CMakeLists.txt | 5 +- .../details/CMakeLists.txt | 3 +- .../lib/rocprofiler-register/details/dl.cpp | 4 +- .../details/environment.hpp | 73 +-- .../lib/rocprofiler-register/details/join.hpp | 184 ------- .../lib/rocprofiler-register/details/log.hpp | 518 ------------------ .../rocprofiler-register/details/utility.cpp | 4 +- .../rocprofiler_register.cpp | 13 +- 17 files changed, 78 insertions(+), 783 deletions(-) create mode 100644 .gitmodules create mode 100644 external/CMakeLists.txt create mode 160000 external/fmt create mode 160000 external/glog delete mode 100644 source/lib/rocprofiler-register/details/join.hpp delete mode 100644 source/lib/rocprofiler-register/details/log.hpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..687f5afc05 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "external/glog"] + path = external/glog + url = https://github.com/google/glog.git +[submodule "external/fmt"] + path = external/fmt + url = https://github.com/fmtlib/fmt.git diff --git a/CMakeLists.txt b/CMakeLists.txt index ef4e70fe66..699529b6fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR enable_testing() include(CTest) +add_subdirectory(external) add_subdirectory(source) if(ROCPROFILER_REGISTER_BUILD_TESTS) diff --git a/cmake/rocprofiler_register_formatting.cmake b/cmake/rocprofiler_register_formatting.cmake index ffc23f0243..05e3c74a4a 100644 --- a/cmake/rocprofiler_register_formatting.cmake +++ b/cmake/rocprofiler_register_formatting.cmake @@ -35,7 +35,8 @@ if(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE set(rocp_source_files) set(rocp_header_files) set(rocp_python_files) - set(rocp_cmake_files ${PROJECT_SOURCE_DIR}/CMakeLists.txt) + set(rocp_cmake_files ${PROJECT_SOURCE_DIR}/CMakeLists.txt + ${PROJECT_SOURCE_DIR}/external/CMakeLists.txt) foreach(_DIR cmake samples source tests) foreach(_TYPE header_files source_files cmake_files python_files) @@ -96,7 +97,7 @@ if(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE endif() endforeach() - foreach(_TYPE source python) + foreach(_TYPE source python cmake) if(TARGET format-rocprofiler-register-${_TYPE}) add_dependencies(format format-rocprofiler-register-${_TYPE}) endif() diff --git a/cmake/rocprofiler_register_linting.cmake b/cmake/rocprofiler_register_linting.cmake index 1a34218e6f..c8398bcd93 100644 --- a/cmake/rocprofiler_register_linting.cmake +++ b/cmake/rocprofiler_register_linting.cmake @@ -27,8 +27,10 @@ macro(ROCPROFILER_REGISTER_ACTIVATE_CLANG_TIDY) ) endif() - set(CMAKE_CXX_CLANG_TIDY ${ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND} - -header-filter=${PROJECT_SOURCE_DIR}/.*) + set(CMAKE_CXX_CLANG_TIDY + ${ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND} + -header-filter=${PROJECT_SOURCE_DIR}/source/.* + --warnings-as-errors=*,-misc-header-include-cycle) # Create a preprocessor definition that depends on .clang-tidy content so the # compile command will change when .clang-tidy changes. This ensures that a diff --git a/cmake/rocprofiler_register_options.cmake b/cmake/rocprofiler_register_options.cmake index e25debc4ae..65d2e0878e 100644 --- a/cmake/rocprofiler_register_options.cmake +++ b/cmake/rocprofiler_register_options.cmake @@ -29,6 +29,8 @@ rocprofiler_register_add_option(ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY rocprofiler_register_add_option( ROCPROFILER_REGISTER_BUILD_DEVELOPER "Extra build flags for development like -Werror" ${ROCPROFILER_REGISTER_BUILD_CI} ADVANCED) +rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_GLOG "Build GLOG" ON) +rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_FMT "Build FMT" ON) # In the future, we will do this even with clang-tidy enabled if(ROCPROFILER_REGISTER_BUILD_CI AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt new file mode 100644 index 0000000000..af77572f22 --- /dev/null +++ b/external/CMakeLists.txt @@ -0,0 +1,33 @@ +set(BUILD_TESTING OFF) + +if(ROCPROFILER_REGISTER_BUILD_GLOG) + # checkout submodule if not already checked out or clone repo if no .gitmodules file + rocprofiler_register_checkout_git_submodule( + RECURSIVE + RELATIVE_PATH glog + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + REPO_URL https://github.com/google/glog.git + REPO_BRANCH "master") + + # May want to use GFLAGS in the future + set(WITH_GFLAGS OFF) + set(BUILD_SHARED_LIBS OFF) + add_subdirectory(glog EXCLUDE_FROM_ALL) +else() + find_package(glog REQUIRED) +endif() + +if(ROCPROFILER_REGISTER_BUILD_FMT) + # checkout submodule if not already checked out or clone repo if no .gitmodules file + rocprofiler_register_checkout_git_submodule( + RECURSIVE + RELATIVE_PATH fmt + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + REPO_URL https://github.com/fmtlib/fmt.git + REPO_BRANCH "master") + + set(FMT_TEST OFF) + add_subdirectory(fmt EXCLUDE_FROM_ALL) +else() + find_package(fmt REQUIRED) +endif() diff --git a/external/fmt b/external/fmt new file mode 160000 index 0000000000..6c845f57e5 --- /dev/null +++ b/external/fmt @@ -0,0 +1 @@ +Subproject commit 6c845f57e5db589208ff0c2808238587cafafa82 diff --git a/external/glog b/external/glog new file mode 160000 index 0000000000..3a0d4d22c5 --- /dev/null +++ b/external/glog @@ -0,0 +1 @@ +Subproject commit 3a0d4d22c5ae0b9a2216988411cfa6bf860cc372 diff --git a/scripts/run-ci.py b/scripts/run-ci.py index f531a6c4c7..c4d9b4eb13 100755 --- a/scripts/run-ci.py +++ b/scripts/run-ci.py @@ -91,7 +91,7 @@ def generate_custom(args, cmake_args, ctest_args): set(CTEST_UPDATE_TYPE git) set(CTEST_UPDATE_VERSION_ONLY TRUE) set(CTEST_GIT_COMMAND {GIT_CMD}) - set(CTEST_GIT_INIT_SUBMODULES FALSE) + set(CTEST_GIT_INIT_SUBMODULES TRUE) set(CTEST_OUTPUT_ON_FAILURE TRUE) set(CTEST_USE_LAUNCHERS TRUE) diff --git a/source/lib/rocprofiler-register/CMakeLists.txt b/source/lib/rocprofiler-register/CMakeLists.txt index f1464bad77..d2ce9959b8 100644 --- a/source/lib/rocprofiler-register/CMakeLists.txt +++ b/source/lib/rocprofiler-register/CMakeLists.txt @@ -20,8 +20,9 @@ target_include_directories( target_link_libraries( rocprofiler-register PUBLIC rocprofiler-register::headers - PRIVATE rocprofiler-register::build-flags rocprofiler-register::memcheck - rocprofiler-register::stdcxxfs rocprofiler-register::dl) + PRIVATE fmt::fmt-header-only glog::glog rocprofiler-register::build-flags + rocprofiler-register::memcheck rocprofiler-register::stdcxxfs + rocprofiler-register::dl) set_target_properties( rocprofiler-register diff --git a/source/lib/rocprofiler-register/details/CMakeLists.txt b/source/lib/rocprofiler-register/details/CMakeLists.txt index 19f7c15568..ef1160ec66 100644 --- a/source/lib/rocprofiler-register/details/CMakeLists.txt +++ b/source/lib/rocprofiler-register/details/CMakeLists.txt @@ -3,8 +3,7 @@ # set(rocprofiler_register_details_sources dl.cpp utility.cpp) -set(rocprofiler_register_details_headers environment.hpp join.hpp dl.hpp log.hpp - utility.hpp) +set(rocprofiler_register_details_headers environment.hpp dl.hpp utility.hpp) target_sources(rocprofiler-register PRIVATE ${rocprofiler_register_details_sources} ${rocprofiler_register_details_headers}) diff --git a/source/lib/rocprofiler-register/details/dl.cpp b/source/lib/rocprofiler-register/details/dl.cpp index 3ae00a688e..5c45c4ec8b 100644 --- a/source/lib/rocprofiler-register/details/dl.cpp +++ b/source/lib/rocprofiler-register/details/dl.cpp @@ -23,7 +23,6 @@ #define GNU_SOURCE 1 #include "dl.hpp" -#include "join.hpp" #include "utility.hpp" #include @@ -34,6 +33,7 @@ #include #include +#include #include #include #include @@ -54,7 +54,7 @@ std::vector get_segment_addresses(pid_t _pid) { auto _data = std::vector{}; - auto _fname = common::join('/', "/proc", _pid, "maps"); + auto _fname = fmt::format("/{}/{}/{}", "proc", _pid, "maps"); auto ifs = std::ifstream{ _fname }; if(!ifs) { diff --git a/source/lib/rocprofiler-register/details/environment.hpp b/source/lib/rocprofiler-register/details/environment.hpp index 03bcf47089..4250ed4de0 100644 --- a/source/lib/rocprofiler-register/details/environment.hpp +++ b/source/lib/rocprofiler-register/details/environment.hpp @@ -20,7 +20,8 @@ #pragma once -#include "log.hpp" +#include "fmt/core.h" +#include "glog/logging.h" #include #include @@ -31,52 +32,6 @@ #include #include -#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_NAME) -# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_NAME) -# define ROCPROFILER_REGISTER_ENVIRON_LOG_NAME \ - "[" ROCPROFILER_REGISTER_COMMON_LIBRARY_NAME "]" -# else -# define ROCPROFILER_REGISTER_ENVIRON_LOG_NAME "[environ]" -# endif -#endif - -#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_START) -# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_START) -# define ROCPROFILER_REGISTER_ENVIRON_LOG_START \ - ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_START -# elif defined(ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE) -# define ROCPROFILER_REGISTER_ENVIRON_LOG_START \ - fprintf(stderr, "%s", ::rocprofiler_register::log::color::dmesg()); -# else -# define ROCPROFILER_REGISTER_ENVIRON_LOG_START -# endif -#endif - -#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_END) -# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_END) -# define ROCPROFILER_REGISTER_ENVIRON_LOG_END \ - ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_END -# elif defined(ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE) -# define ROCPROFILER_REGISTER_ENVIRON_LOG_END \ - fprintf(stderr, "%s", ::rocprofiler_register::log::color::end()); -# else -# define ROCPROFILER_REGISTER_ENVIRON_LOG_END -# endif -#endif - -#define ROCPROFILER_REGISTER_ENVIRON_LOG(CONDITION, ...) \ - if(CONDITION) \ - { \ - fflush(stderr); \ - ROCPROFILER_REGISTER_ENVIRON_LOG_START \ - fprintf(stderr, \ - "[rocprofiler-register]" ROCPROFILER_REGISTER_ENVIRON_LOG_NAME "[%i] ", \ - getpid()); \ - fprintf(stderr, __VA_ARGS__); \ - ROCPROFILER_REGISTER_ENVIRON_LOG_END \ - fflush(stderr); \ - } - namespace rocprofiler_register { namespace common @@ -110,14 +65,13 @@ get_env_impl(std::string_view env_id, int _default) return std::stoi(env_var); } catch(std::exception& _e) { - fprintf(stderr, - "[rocprofiler_register][get_env] Exception thrown converting " - "getenv(\"%s\") = " - "%s to integer :: %s. Using default value of %i\n", - env_id.data(), - env_var, - _e.what(), - _default); + LOG(ERROR) << fmt::format( + "[rocprofiler_register][get_env] Exception thrown converting getenv({}) " + "= {} to integer :: {}. Using default value of {}", + env_id.data(), + env_var, + _e.what(), + _default); } return _default; } @@ -176,14 +130,11 @@ struct env_config std::string env_value = {}; int override = 0; - auto operator()(bool _verbose = false) const + auto operator()() const { if(env_name.empty()) return -1; - ROCPROFILER_REGISTER_ENVIRON_LOG(_verbose, - "setenv(\"%s\", \"%s\", %i)\n", - env_name.c_str(), - env_value.c_str(), - override); + LOG(INFO) << fmt::format( + "setenv({}, {}, {})", env_name.c_str(), env_value.c_str(), override); return setenv(env_name.c_str(), env_value.c_str(), override); } }; diff --git a/source/lib/rocprofiler-register/details/join.hpp b/source/lib/rocprofiler-register/details/join.hpp deleted file mode 100644 index 0086560dcf..0000000000 --- a/source/lib/rocprofiler-register/details/join.hpp +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2023 Advanced Micro Devices, Inc. -// -// 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 -#include -#include -#include -#include -#include -#include -#include - -#if !defined(ROCPROFILER_REGISTER_FOLD_EXPRESSION) -# define ROCPROFILER_REGISTER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...) -#endif - -namespace rocprofiler_register -{ -namespace common -{ -namespace -{ -template -struct is_string_impl : std::false_type -{ }; - -template <> -struct is_string_impl : std::true_type -{ }; - -template <> -struct is_string_impl : std::true_type -{ }; - -template <> -struct is_string_impl : std::true_type -{ }; - -template <> -struct is_string_impl : std::true_type -{ }; - -template -struct is_string : is_string_impl>> -{ }; - -template -auto -as_string(ArgT&& _v, std::enable_if_t::value, int> = 0) -{ - if constexpr(std::is_pointer>::value) - { - return (_v == nullptr) ? std::string{ "\"\"" } - : (std::string{ "\"" } + _v + std::string{ "\"" }); - } - else - { - return std::string{ "\"" } + _v + std::string{ "\"" }; - } -} - -template -auto -as_string(ArgT&& _v, std::enable_if_t::value, long> = 0) -{ - return _v; -} - -template -auto -join(DelimT&& _delim, Args&&... _args) -{ - using delim_type = std::remove_cv_t>; - - std::stringstream _ss{}; - _ss << std::boolalpha; - - if constexpr(std::is_same::value) - { - const char _delim_c[2] = { _delim, '\0' }; - ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim_c << _args); - auto _ret = _ss.str(); - return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; - } - else - { - ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim << _args); - auto _ret = _ss.str(); - auto&& _len = std::string{ _delim }.length(); - return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; - } -} - -struct QuoteStrings -{ }; - -template -auto -join(QuoteStrings&&, DelimT&& _delim, Args&&... _args) -{ - using delim_type = std::remove_cv_t>; - - std::stringstream _ss{}; - _ss << std::boolalpha; - - if constexpr(std::is_same::value) - { - const char _delim_c[2] = { _delim, '\0' }; - ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim_c << as_string(_args)); - auto _ret = _ss.str(); - return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; - } - else - { - ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim << as_string(_args)); - auto _ret = _ss.str(); - auto&& _len = std::string{ _delim }.length(); - return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; - } -} - -template -auto -join(std::array&& _delim, Args&&... _args) -{ - return join("", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} - -template -auto -join(QuoteStrings&&, std::array&& _delim, Args&&... _args) -{ - return join(QuoteStrings{}, - "", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} - -template -auto -join(std::tuple&& _delim, Args&&... _args) -{ - return join("", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} - -template -auto -join(QuoteStrings&&, std::tuple&& _delim, Args&&... _args) -{ - return join(QuoteStrings{}, - "", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} -} // namespace -} // namespace common -} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/details/log.hpp b/source/lib/rocprofiler-register/details/log.hpp deleted file mode 100644 index bc9ecf7c75..0000000000 --- a/source/lib/rocprofiler-register/details/log.hpp +++ /dev/null @@ -1,518 +0,0 @@ -// 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 rhs -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR rhsWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR rhs DEALINGS IN THE -// SOFTWARE. - -#pragma once - -#include - -#ifndef ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE -# define ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE 1 -#endif - -#ifndef ROCPROFILER_REGISTER_PROJECT_NAME -# define ROCPROFILER_REGISTER_PROJECT_NAME "rocprofiler-register" -#endif - -#ifndef ROCP_REG_FILE_NAME -# define ROCP_REG_FILE_NAME \ - ::std::string{ __FILE__ } \ - .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ - .c_str() -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace rocprofiler_register -{ -namespace log -{ -bool& -monochrome(); - -inline bool& -monochrome() -{ - static bool _v = []() { - auto _val = false; - const char* _env_cstr = nullptr; - _env_cstr = std::getenv("ROCPROFILER_REGISTER_MONOCHROME"); - - if(!_env_cstr) _env_cstr = std::getenv("MONOCHROME"); - - if(_env_cstr) - { - auto _env = std::string{ _env_cstr }; - - // check if numeric - if(_env.find_first_not_of("0123456789") == std::string::npos) - { - return _env.length() > 1 || _env[0] != '0'; - } - - for(auto& itr : _env) - itr = tolower(itr); - - // check for matches to acceptable forms of false - for(const auto& itr : { "off", "false", "no", "n", "f" }) - { - if(_env == itr) return false; - } - - // check for matches to acceptable forms of true - for(const auto& itr : { "on", "true", "yes", "y", "t" }) - { - if(_env == itr) return true; - } - } - return _val; - }(); - return _v; -} - -namespace color -{ -static constexpr auto info_value = "\033[01;34m"; -static constexpr auto warning_value = "\033[01;33m"; -static constexpr auto fatal_value = "\033[01;31m"; -static constexpr auto source_value = "\033[01;32m"; -static constexpr auto dmesg_value = "\033[01;37m"; -static constexpr auto end_value = "\033[0m"; - -inline const char* -info() -{ - return (log::monochrome()) ? "" : info_value; -} - -inline const char* -warning() -{ - return (log::monochrome()) ? "" : warning_value; -} - -inline const char* -fatal() -{ - return (log::monochrome()) ? "" : fatal_value; -} - -inline const char* -source() -{ - return (log::monochrome()) ? "" : source_value; -} - -inline const char* -dmesg() -{ - return (log::monochrome()) ? "" : dmesg_value; -} - -inline const char* -end() -{ - return (log::monochrome()) ? "" : end_value; -} -} // namespace color -} // namespace log -} // namespace rocprofiler_register - -namespace rocprofiler_register -{ -namespace log -{ -struct base -{ -public: - static base indent(size_t, size_t = 2) { return base{}; } - - template - auto operator<<(Tp&&) - { - return base{}; - } -}; - -struct logger : public base -{ - logger() = default; - - explicit logger(bool _exit) - : m_exit{ _exit } - { } - - ~logger() - { - if(m_done) - { - std::cerr << color::end() << "\n"; - if(m_exit) abort(); - } - } - - logger(logger&& rhs) noexcept - { - m_exit = rhs.m_exit; - m_done = rhs.m_done; - rhs.m_done = false; - } - - logger& operator=(logger&& rhs) noexcept - { - m_exit = rhs.m_exit; - m_done = rhs.m_done; - rhs.m_done = false; - return *this; - } - - logger&& indent(size_t _n, size_t _tab_size = 4) - { - for(size_t i = 0; i < _n; i++) - for(size_t j = 0; j < _tab_size; j++) - std::cerr << " "; - return std::move(*this); - } - - template - logger&& operator<<(Tp&& _v) - { - std::cerr << std::forward(_v); - return std::move(*this); - } - -private: - bool m_exit = false; - bool m_done = true; -}; - -template -inline auto& -get_color_hist() -{ - static thread_local std::vector> _v{}; - return _v; -} - -template -inline auto -push_color_hist(Tp* _v, const char* _c) -{ - if(!monochrome()) get_color_hist().emplace_back(_v, _c); - return _c; -} - -template -inline std::string -pop_color_hist(Tp* _v) -{ - if(monochrome()) return std::string{}; - - auto& _hist = get_color_hist(); - for(auto itr = _hist.rbegin(); itr != _hist.rend(); ++itr) - { - Tp* _addr = itr->first; - if(_addr == _v) - { - auto fitr = _hist.begin(); - std::advance(fitr, std::distance(_hist.rbegin(), itr)); - _hist.erase(fitr); - } - } - for(auto itr = _hist.rbegin(); itr != _hist.rend(); ++itr) - { - if(itr->first == _v) return itr->second; - } - return color::end(); -} - -template -std::basic_ostream& -info(std::basic_ostream& os) -{ - return (os << push_color_hist(&os, color::info())); -} - -template -std::basic_ostream& -warning(std::basic_ostream& os) -{ - return (os << push_color_hist(&os, color::warning())); -} - -template -std::basic_ostream& -fatal(std::basic_ostream& os) -{ - return (os << push_color_hist(&os, color::fatal())); -} - -template -std::basic_ostream& -source(std::basic_ostream& os) -{ - return (os << push_color_hist(&os, color::source())); -} - -template -std::basic_ostream& -end(std::basic_ostream& os) -{ - return (os << push_color_hist(&os, color::end())); -} - -template -std::basic_ostream& -pop(std::basic_ostream& os) -{ - return (os << pop_color_hist(&os)); -} - -template -std::basic_ostream& -reset(std::basic_ostream& os) -{ - pop_color_hist(&os); - return (os << color::end()); -} - -template -std::basic_ostream& -flush(std::basic_ostream& os) -{ - return (os << pop << std::flush); -} - -template -std::basic_ostream& -endl(std::basic_ostream& os) -{ - return (os << pop << "\n" << std::flush); -} - -template -struct stream_base -{ - stream_base(StreamT& _os, const char* _color) - : m_os{ _os } - { - m_os << push_color_hist(&_os, _color); - } - - ~stream_base() { m_os << pop_color_hist(&m_os); } - - stream_base(const stream_base&) = delete; - stream_base& operator=(const stream_base&) = delete; - - stream_base(stream_base&& rhs) noexcept = default; - stream_base& operator=(stream_base&& rhs) noexcept = default; - - template - stream_base& operator<<(Tp&& _v) - { - m_os << std::forward(_v); - return *this; - } - - template - stream_base& operator<<(Tp& _v) - { - m_os << _v; - return *this; - } - - stream_base& put(char _c) - { - m_os.put(_c); - return *this; - } - - stream_base& endl() - { - m_os << std::endl; - return *this; - } - - template - stream_base& write(Args&&... _args) - { - m_os.write(std::forward(_args)...); - return *this; - } - - stream_base& flush() - { - m_os << std::flush; - return *this; - } - - auto tellp() { return m_os.tellp(); } - - template - stream_base& seekp(Args&&... _args) - { - m_os.seekp(std::forward(_args)...); - return *this; - } - -private: - StreamT& m_os; -}; - -template -stream_base -stream(StreamT& _os, const char* _color) -{ - return stream_base{ _os, _color }; -} - -template -stream_base -info_stream(StreamT& _os) -{ - return stream_base{ _os, color::info() }; -} - -template -stream_base -source_stream(StreamT& _os) -{ - return stream_base{ _os, color::source() }; -} - -template -stream_base -warning_stream(StreamT& _os) -{ - return stream_base{ _os, color::warning() }; -} - -template -stream_base -fatal_stream(StreamT& _os) -{ - return stream_base{ _os, color::fatal() }; -} - -inline std::string -string(const char* _color, std::string_view _v) -{ - return std::string{ _color } + std::string{ _v } + std::string{ color::end() }; -} - -inline std::string -string(const char* _color, std::stringstream& _v) -{ - return std::string{ _color } + _v.str() + std::string{ color::end() }; -} - -inline std::string -string(const char* _color, std::stringstream&& _v) -{ - return std::string{ _color } + _v.str() + std::string{ color::end() }; -} - -template -inline auto -info_string(Tp&& _v) -{ - return string(color::info(), std::forward(_v)); -} - -template -inline auto -source_string(Tp&& _v) -{ - return string(color::source(), std::forward(_v)); -} - -template -inline auto -warning_string(Tp&& _v) -{ - return string(color::warning(), std::forward(_v)); -} - -template -inline auto -fatal_string(Tp&& _v) -{ - return string(color::fatal(), std::forward(_v)); -} -} // namespace log -} // namespace rocprofiler_register - -#if !defined(ROCPROFILER_REGISTER_LOG) -# define ROCPROFILER_REGISTER_LOG(COLOR, EXIT_CODE) \ - (::rocprofiler_register::log::logger(EXIT_CODE) \ - << ::rocprofiler_register::log::color::end() \ - << ::rocprofiler_register::log::color::source() << "[" \ - << ROCPROFILER_REGISTER_PROJECT_NAME << "][" << ROCP_REG_FILE_NAME << ":" \ - << __LINE__ << "][" << getpid() << "] " \ - << ::rocprofiler_register::log::color::end() << COLOR) -#endif - -#if defined(NDEBUG) -# if !defined(ROCPROFILER_REGISTER_INFO) -# define ROCPROFILER_REGISTER_INFO (::rocprofiler_register::log::base()) -# endif -# if !defined(ROCPROFILER_REGISTER_ASSERT) -# define ROCPROFILER_REGISTER_ASSERT(COND) (::rocprofiler_register::log::base()) -# endif -#else -# if !defined(ROCPROFILER_REGISTER_INFO) -# define ROCPROFILER_REGISTER_INFO \ - ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::info(), false) -# endif -# if !defined(ROCPROFILER_REGISTER_ASSERT) -# define ROCPROFILER_REGISTER_ASSERT(COND) \ - (COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_FATAL -# endif -#endif - -#if !defined(ROCPROFILER_REGISTER_WARNING) -# define ROCPROFILER_REGISTER_WARNING \ - ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::warning(), false) -#endif - -#if !defined(ROCPROFILER_REGISTER_FATAL) -# define ROCPROFILER_REGISTER_FATAL \ - ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::fatal(), true) -#endif - -#if !defined(ROCPROFILER_REGISTER_PREFER) -# define ROCPROFILER_REGISTER_PREFER(COND) \ - (COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_WARNING -#endif - -#if !defined(ROCPROFILER_REGISTER_REQUIRE) -# define ROCPROFILER_REGISTER_REQUIRE(COND) \ - (COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_FATAL -#endif diff --git a/source/lib/rocprofiler-register/details/utility.cpp b/source/lib/rocprofiler-register/details/utility.cpp index 7a72ba729d..cc9e9fc6b1 100644 --- a/source/lib/rocprofiler-register/details/utility.cpp +++ b/source/lib/rocprofiler-register/details/utility.cpp @@ -92,9 +92,9 @@ delimit(const std::string& line, std::string_view delimiters) size_t _nmax = 0; for(char itr : line) { - for(size_t j = 0; j < delimiters.length(); ++j) + for(char delimiter : delimiters) { - if(itr == delimiters.at(j)) ++_nmax; + if(itr == delimiter) ++_nmax; } } reserve(_result, _nmax); diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 55cd1ab4c7..a2eb28fa7e 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -24,7 +24,7 @@ #include "details/dl.hpp" #include "details/environment.hpp" -#include "details/log.hpp" +#include "glog/logging.h" #include #include @@ -140,7 +140,7 @@ get_this_library_path() { auto _this_lib_path = binary::get_linked_path(rocprofiler_register_lib_name, { RTLD_NOLOAD | RTLD_LAZY }); - ROCPROFILER_REGISTER_REQUIRE(_this_lib_path) + LOG_IF(FATAL, !_this_lib_path) << rocprofiler_register_lib_name << " could not locate itself in the list of loaded libraries"; return fs::path{ *_this_lib_path }.parent_path().string(); @@ -223,16 +223,15 @@ rocp_reg_scan_for_tools() } if(rocprofiler_register_verbose >= rocprofiler_register_info_level) - ROCPROFILER_REGISTER_INFO << "loaded " << _rocp_reg_lib_path_fname.string() - << " library at " << _rocp_reg_lib_path.string(); + LOG(INFO) << "loaded " << _rocp_reg_lib_path_fname.string() << " library at " + << _rocp_reg_lib_path.string(); - ROCPROFILER_REGISTER_REQUIRE(rocprofiler_lib_handle) - << _rocp_reg_lib << " failed to load\n"; + LOG_IF(FATAL, !rocprofiler_lib_handle) << _rocp_reg_lib << " failed to load\n"; *(void**) (&rocprofiler_lib_config_fn) = dlsym(rocprofiler_lib_handle, rocprofiler_lib_register_entrypoint); - ROCPROFILER_REGISTER_REQUIRE(rocprofiler_lib_config_fn) + LOG_IF(FATAL, !rocprofiler_lib_config_fn) << _rocp_reg_lib << " did not contain '" << rocprofiler_lib_register_entrypoint << "' symbol\n"; } From 5a6ac895d1acc5d4836f29f9740e245d8a5ec5fe Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Tue, 26 Sep 2023 13:50:23 -0500 Subject: [PATCH 04/49] Sync with rocprofiler updates (#26) - Update rocprofiler_configure prototype - add compile_commands.json to .gitignore --- .gitignore | 1 + cmake/rocprofiler_register_options.cmake | 4 +- .../rocprofiler-register.h | 23 ++++++++--- .../rocprofiler_register.cpp | 9 +++-- tests/rocprofiler/rocprofiler.cpp | 38 +++++++++++++------ 5 files changed, 52 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index ff0a008fec..eb974bc1f1 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ # Build directories /build* /.cache +/compile_commands.json diff --git a/cmake/rocprofiler_register_options.cmake b/cmake/rocprofiler_register_options.cmake index 65d2e0878e..5d4385769a 100644 --- a/cmake/rocprofiler_register_options.cmake +++ b/cmake/rocprofiler_register_options.cmake @@ -20,8 +20,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_TESTS "Enable building the tests" OFF) -rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_SAMPLES "Enable building the - code samples" OFF) +rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_SAMPLES + "Enable building the code samples" OFF) rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_CI "Enable continuous integration additions" OFF ADVANCED) rocprofiler_register_add_option(ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY diff --git a/source/include/rocprofiler-register/rocprofiler-register.h b/source/include/rocprofiler-register/rocprofiler-register.h index b49c1c8cdb..79a89fd1b8 100644 --- a/source/include/rocprofiler-register/rocprofiler-register.h +++ b/source/include/rocprofiler-register/rocprofiler-register.h @@ -22,20 +22,33 @@ #include +#include #include #ifdef __cplusplus extern "C" { #endif -typedef int (*rocprofiler_configure_callback_t)(void*); +typedef struct +{ + const char* name; ///< clients should set this value for debugging + const uint32_t handle; ///< internal handle +} rocprofiler_client_id_t; + +typedef void (*rocprofiler_client_finalize_t)(rocprofiler_client_id_t); + +typedef int (*rocprofiler_tool_initialize_t)(rocprofiler_client_finalize_t finalize_func, + void* tool_data); + +typedef void (*rocprofiler_tool_finalize_t)(void* tool_data); typedef struct { - rocprofiler_configure_callback_t initialize; - rocprofiler_configure_callback_t finalize; - void* user_data; -} rocprofiler_configure_result_t; + size_t size; ///< in case of future extensions + rocprofiler_tool_initialize_t initialize; ///< context creation + rocprofiler_tool_finalize_t finalize; ///< cleanup + void* tool_data; ///< data to provide to init and fini callbacks +} rocprofiler_tool_configure_result_t; typedef uint32_t (*rocprofiler_register_import_func_t)(void); diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index a2eb28fa7e..a9329b5753 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -48,8 +48,8 @@ extern "C" { #pragma weak rocprofiler_register_import_roctx #pragma weak rocprofiler_register_import_roctx_static -extern rocprofiler_configure_result_t* -rocprofiler_configure(uint32_t, const char*, uint32_t, uint32_t); +extern rocprofiler_tool_configure_result_t* +rocprofiler_configure(uint32_t, const char*, uint32_t, rocprofiler_client_id_t*); extern int rocprofiler_set_api_table(const char*, uint64_t, uint64_t, void**, uint64_t); @@ -226,12 +226,13 @@ rocp_reg_scan_for_tools() LOG(INFO) << "loaded " << _rocp_reg_lib_path_fname.string() << " library at " << _rocp_reg_lib_path.string(); - LOG_IF(FATAL, !rocprofiler_lib_handle) << _rocp_reg_lib << " failed to load\n"; + LOG_IF(FATAL, rocprofiler_lib_handle == nullptr) + << _rocp_reg_lib << " failed to load\n"; *(void**) (&rocprofiler_lib_config_fn) = dlsym(rocprofiler_lib_handle, rocprofiler_lib_register_entrypoint); - LOG_IF(FATAL, !rocprofiler_lib_config_fn) + LOG_IF(FATAL, rocprofiler_lib_config_fn == nullptr) << _rocp_reg_lib << " did not contain '" << rocprofiler_lib_register_entrypoint << "' symbol\n"; } diff --git a/tests/rocprofiler/rocprofiler.cpp b/tests/rocprofiler/rocprofiler.cpp index 9b26feb342..de24381253 100644 --- a/tests/rocprofiler/rocprofiler.cpp +++ b/tests/rocprofiler/rocprofiler.cpp @@ -42,26 +42,40 @@ roctx_range_pop(const char* name) } // namespace rocprofiler extern "C" { -struct rocprofiler_configure_result_t +typedef struct { - int (*initialize)(void*) = nullptr; - int (*finalize)(void*) = nullptr; - void* data = nullptr; -}; + const char* name; ///< clients should set this value for debugging + const uint32_t handle; ///< internal handle +} rocprofiler_client_id_t; -rocprofiler_configure_result_t* -rocprofiler_configure(uint32_t, const char*, uint32_t, uint32_t) +typedef void (*rocprofiler_client_finalize_t)(rocprofiler_client_id_t); + +typedef int (*rocprofiler_tool_initialize_t)(rocprofiler_client_finalize_t finalize_func, + void* tool_data); + +typedef void (*rocprofiler_tool_finalize_t)(void* tool_data); + +typedef struct +{ + size_t size; ///< in case of future extensions + rocprofiler_tool_initialize_t initialize; ///< context creation + rocprofiler_tool_finalize_t finalize; ///< cleanup + void* tool_data; ///< data to provide to init and fini callbacks +} rocprofiler_tool_configure_result_t; + +rocprofiler_tool_configure_result_t* +rocprofiler_configure(uint32_t, const char*, uint32_t, rocprofiler_client_id_t*) __attribute__((visibility("default"))); int rocprofiler_set_api_table(const char*, uint64_t, uint64_t, void**, uint64_t) __attribute__((visibility("default"))); -rocprofiler_configure_result_t* -rocprofiler_configure(uint32_t version, - const char* runtime_version, - uint32_t priority, - uint32_t tool_id) +rocprofiler_tool_configure_result_t* +rocprofiler_configure(uint32_t version, + const char* runtime_version, + uint32_t priority, + rocprofiler_client_id_t* tool_id) { (void) version; (void) runtime_version; From 40f37f9597d928213a81a4adfbd2414a8d464cb1 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Thu, 19 Oct 2023 03:47:27 -0500 Subject: [PATCH 05/49] Update README and workflows (#27) * Update README - Overview - Contributing - Build and install * Update workflows - branches reflect new amd-mainline and amd-staging names instead of main and develop --- .github/workflows/continuous-integration.yml | 4 +- .github/workflows/formatting.yml | 2 +- README.md | 62 +++++++++++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 4959f58ee0..2235140a6e 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -2,11 +2,11 @@ name: Continuous Integration on: push: - branches: [ main, develop ] + branches: [ amd-mainline, amd-staging ] paths-ignore: - '*.md' pull_request: - branches: [ main, develop ] + branches: [ amd-mainline, amd-staging ] paths-ignore: - '*.md' diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 7cbbb93f75..7fca0a0777 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -4,7 +4,7 @@ name: Formatting on: workflow_dispatch: pull_request: - branches: [ main ] + branches: [ amd-mainline, amd-staging ] paths-ignore: - '.github/workflows/pull_*.yml' - '.github/workflows/linting.yml' diff --git a/README.md b/README.md index 8f8bcf1a62..5ce882f48e 100644 --- a/README.md +++ b/README.md @@ -1 +1,61 @@ -# rocprofiler-register \ No newline at end of file +# rocprofiler-register + +## Overview + +The rocprofiler-register library is a helper library that coordinates the modification of the intercept API table(s) of the HSA/HIP/ROCTx +runtime libraries by the ROCprofiler (v2) library. The purpose of this library is to provide a consistent and automated mechanism +of enabling performance analysis in the ROCm runtimes which does not rely on environment variables or unique methods for each runtime +library. + +When a runtime is initialized (either explicitly and lazily) and the intercept API table is constructed, it passes this API table to +rocprofiler-register. Rocprofiler-register scans the symbols in the address space and if it detects there is at least one visible symbol named +`rocprofiler_configure` (which is a function provided by tools), it passes the intercept API table to the rocprofiler library (dlopening +the rocprofiler library if it is not already loaded). The rocprofiler library then does an extensive scan for _all_ the instances of +the `rocprofiler_configure` symbols and invokes each of them. The `rocprofiler_configure` function (again, provided by a tool) returns +effectively tells rocprofiler which behaviors it wants to be notified about, features it wants to use (e.g. API tracing, kernel dispatch timing), +etc. + +## Contributing + +The default branch is `amd-mainline` but the only branch that should target that branch in a pull requests is the `amd-staging` branch. + +> _**All pull-requests should target the `amd-staging` branch**_ + +### Creating a feature branch + +```console +# fetch any updates +git fetch origin + +# switch to staging branch +git checkout amd-staging + +# update your copy of the staging branch +git pull --rebase + +# create your feature branch off of amd-staging +git checkout -b +``` + +In the event, your local clone of the repo has a `amd-staging` branch that diverges from the upstream branch, +do a hard reset of your local branch to match the upstream branch: `git reset --hard origin/amd-staging`. +Theoretically, you should never need to do this for `amd-mainline` but this can be applied to that +branch as well. + +### Pulling in updates to `amd-staging` to your feature branch + +Linear histories are preferred so if another PR is merged into `amd-staging` while your PR is still open, please +select the "Update with rebase" option (i.e. try to avoid a merge commit). From the command line, the git command +would be `git pull --rebase origin amd-staging`. + +## Build and Installation + +rocprofiler-register has a standard CMake build and install process. E.g. the following configure +rocprofiler-register to build with optimizations and without debug info in a `build-rocp-reg` subdirectory, +build using 4 jobs, and install to `/opt/rocprofiler-register`: + +```console +cmake -B build-rocp-reg . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/rocprofiler-register +cmake --build build-rocp-reg --target all --parallel 4 +cmake --build build-rocp-reg --target install +``` From 24041c4d874815aab35b9249bd045e3ef2ceb0c7 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Wed, 25 Oct 2023 04:17:34 -0500 Subject: [PATCH 06/49] C++ filesystem and link to dl library in test exe (#29) * Add lib/rocprofiler-register/details/filesystem.hpp - this provides backwards compatibility for compiler which do not have - use when not available * Update tests/CMakeLists.txt - test executables link to dl library (via CMAKE_DL_LIBS) * Update CI workflow - include ubuntu-20.04 jobs --- .github/workflows/continuous-integration.yml | 8 ++++ .../details/CMakeLists.txt | 3 +- .../lib/rocprofiler-register/details/dl.cpp | 4 +- .../details/filesystem.hpp | 48 +++++++++++++++++++ .../rocprofiler_register.cpp | 3 +- tests/CMakeLists.txt | 11 ++++- 6 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 source/lib/rocprofiler-register/details/filesystem.hpp diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 2235140a6e..0a27dec6ba 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -32,6 +32,14 @@ jobs: compiler: 'clang-15' ci-args: '--linter clang-tidy' ci-tag: '-clang-tidy' + - runner: 'ubuntu-20.04' + compiler: 'gcc-9' + ci-args: '' + ci-tag: '' + - runner: 'ubuntu-20.04' + compiler: 'clang-10' + ci-args: '' + ci-tag: '' # - runner: 'ubuntu-latest' # compiler: 'gcc-12' # ci-args: '--memcheck ThreadSanitizer' diff --git a/source/lib/rocprofiler-register/details/CMakeLists.txt b/source/lib/rocprofiler-register/details/CMakeLists.txt index ef1160ec66..71587dbd81 100644 --- a/source/lib/rocprofiler-register/details/CMakeLists.txt +++ b/source/lib/rocprofiler-register/details/CMakeLists.txt @@ -3,7 +3,8 @@ # set(rocprofiler_register_details_sources dl.cpp utility.cpp) -set(rocprofiler_register_details_headers environment.hpp dl.hpp utility.hpp) +set(rocprofiler_register_details_headers environment.hpp dl.hpp filesystem.hpp + utility.hpp) target_sources(rocprofiler-register PRIVATE ${rocprofiler_register_details_sources} ${rocprofiler_register_details_headers}) diff --git a/source/lib/rocprofiler-register/details/dl.cpp b/source/lib/rocprofiler-register/details/dl.cpp index 5c45c4ec8b..4a1e52327b 100644 --- a/source/lib/rocprofiler-register/details/dl.cpp +++ b/source/lib/rocprofiler-register/details/dl.cpp @@ -23,9 +23,9 @@ #define GNU_SOURCE 1 #include "dl.hpp" +#include "filesystem.hpp" #include "utility.hpp" -#include #include #include #include @@ -38,8 +38,6 @@ #include #include -namespace fs = ::std::filesystem; - namespace rocprofiler_register { namespace binary diff --git a/source/lib/rocprofiler-register/details/filesystem.hpp b/source/lib/rocprofiler-register/details/filesystem.hpp new file mode 100644 index 0000000000..550ce92a8f --- /dev/null +++ b/source/lib/rocprofiler-register/details/filesystem.hpp @@ -0,0 +1,48 @@ +// 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 + +#if defined __has_include +# if __has_include() +# include +# endif +#endif + +#if defined(__cpp_lib_filesystem) +# define ROCPROFILER_REGISTER_HAS_CPP_LIB_FILESYSTEM 1 +#else +# if defined __has_include +# if __has_include() +# include +# endif +# endif +#endif + +#if defined(ROCPROFILER_REGISTER_HAS_CPP_LIB_FILESYSTEM) && \ + ROCPROFILER_REGISTER_HAS_CPP_LIB_FILESYSTEM > 0 +# include +namespace fs = ::std::filesystem; // NOLINT +#else +# include +namespace fs = ::std::experimental::filesystem; // NOLINT +#endif diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index a9329b5753..548b0ae540 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -24,12 +24,12 @@ #include "details/dl.hpp" #include "details/environment.hpp" +#include "details/filesystem.hpp" #include "glog/logging.h" #include #include #include -#include #include #include #include @@ -75,7 +75,6 @@ rocprofiler_register_import_roctx_static(void); namespace { -namespace fs = ::std::filesystem; using namespace rocprofiler_register; using rocprofiler_set_api_table_t = decltype(::rocprofiler_set_api_table)*; using bitset_t = std::bitset; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fc1c741ab6..077f647862 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,6 +56,14 @@ function(rocp_register_strip_target) endif() endfunction() +if(NOT CMAKE_DL_LIBS) + find_library(DL_LIBRARY NAMES dl) + if(NOT DL_LIBRARY) + set(DL_LIBRARY dl) + endif() + set(CMAKE_DL_LIBS ${DL_LIBRARY}) +endif() + # # mock libraries # @@ -72,7 +80,8 @@ find_package(Threads REQUIRED) add_library(rocprofiler-register-tests-common INTERFACE) target_include_directories(rocprofiler-register-tests-common INTERFACE $) -target_link_libraries(rocprofiler-register-tests-common INTERFACE Threads::Threads stdc++) +target_link_libraries(rocprofiler-register-tests-common INTERFACE Threads::Threads stdc++ + ${CMAKE_DL_LIBS}) add_library(rocprofiler-register-tests-strong INTERFACE) target_compile_definitions(rocprofiler-register-tests-strong From 5aa94a7160adaac8d6f6a68d04c380faff3ae2a2 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Thu, 26 Oct 2023 08:59:51 -0500 Subject: [PATCH 07/49] Fixing ROCM Patch Version issue (#30) --- cmake/rocprofiler_register_config_packaging.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index 4e13119443..e07ecd968d 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -7,7 +7,7 @@ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}") set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") -set(CPACK_PACKAGE_CONTACT "jonathan.madsen@amd.com") +set(CPACK_PACKAGE_CONTACT "ROCm Profiler Support ") set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) set(ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME @@ -96,5 +96,9 @@ set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}" ) +if(DEFINED ENV{ROCM_LIBPATCH_VERSION}) + set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}.$ENV{ROCM_LIBPATCH_VERSION}") + message("Using CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}") +endif() include(CPack) From 6af827cd91c4a821eaf3c468ceca419ffc08d80b Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Fri, 3 Nov 2023 06:57:39 -0500 Subject: [PATCH 08/49] Update .gitignore (#33) * Update .gitignore * Update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index eb974bc1f1..9e03c05ae7 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ /build* /.cache /compile_commands.json + +# Github Workflows +/.github/workflows/continuous-integration.yml From ed1938479d894748869ec2e04ef1f9b79f899fee Mon Sep 17 00:00:00 2001 From: Gopesh Bhardwaj Date: Tue, 28 Nov 2023 20:06:07 +0530 Subject: [PATCH 09/49] SWDEV-431048 Fixing rocprofiler-register package dependencies (#44) * SWDEV-431048 Fixing rocprofiler-register package dependencies * cmake formatting (cmake-format) (#45) Co-authored-by: bgopesh * Apply suggestions from code review --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: bgopesh Co-authored-by: Jonathan R. Madsen --- cmake/rocprofiler_register_config_packaging.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index e07ecd968d..648e788873 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -46,7 +46,7 @@ if(DEFINED ENV{CPACK_DEBIAN_PACKAGE_RELEASE}) set(CPACK_DEBIAN_PACKAGE_RELEASE $ENV{CPACK_DEBIAN_PACKAGE_RELEASE}) endif() -set(_DEBIAN_PACKAGE_DEPENDS "") +set(_DEBIAN_PACKAGE_DEPENDS "rocm-core") if(rocm_version_FOUND) set(_ROCPROFILER_REGISTER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})") set(_ROCTRACER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})") @@ -81,6 +81,13 @@ if(DEFINED ENV{CPACK_RPM_PACKAGE_RELEASE}) set(CPACK_RPM_PACKAGE_RELEASE $ENV{CPACK_RPM_PACKAGE_RELEASE}) endif() +set(_RPM_PACKAGE_DEPENDS "rocm-core") +string(REPLACE ";" ", " _RPM_PACKAGE_DEPENDS "${_RPM_PACKAGE_DEPENDS}") +set(CPACK_RPM_PACKAGE_REQUIRES + "${_RPM_PACKAGE_DEPENDS}" + CACHE STRING "RPM package dependencies" FORCE) +rocprofiler_register_add_feature(CPACK_RPM_PACKAGE_REQUIRES "RPM package dependencies") + # Get rpm distro if(CPACK_RPM_PACKAGE_RELEASE) set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) From b04c8478f215e40548b66223691d157a90a51a76 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Tue, 28 Nov 2023 18:15:40 -0600 Subject: [PATCH 10/49] Build System Fixes (#46) * Update build system - emsure CMAKE_INSTALL_LIBDIR is always lib - fix find_package(rocprofiler-register) in build tree - set rocprofiler-register_VERSION in rocprofiler-register-config.cmake - samples/library-implementation always uses find_package(rocprofiler-register) * Update cmake/rocprofiler_register_config_install.cmake - rocprofiler_register_DIR -> rocprofiler-register_DIR --- CMakeLists.txt | 7 +++++-- .../rocprofiler-register-config.cmake.in | 6 +++++- cmake/rocprofiler_register_config_install.cmake | 16 +++++++++++++--- samples/library-implementation/CMakeLists.txt | 13 +++++++------ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 699529b6fa..51e0a05004 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,9 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${PROJECT_SOURCE_DIR}/cmake/Mo include(GNUInstallDirs) # install directories +# ROCm does not use lib64 +set(CMAKE_INSTALL_LIBDIR "lib") + include(rocprofiler_register_utilities) # various functions/macros include(rocprofiler_register_interfaces) # interface libraries include(rocprofiler_register_compilers) # compiler identification @@ -96,6 +99,8 @@ include(CTest) add_subdirectory(external) add_subdirectory(source) +include(rocprofiler_register_config_install) + if(ROCPROFILER_REGISTER_BUILD_TESTS) add_subdirectory(tests) endif() @@ -104,8 +109,6 @@ if(ROCPROFILER_REGISTER_BUILD_SAMPLES) add_subdirectory(samples) endif() -# -include(rocprofiler_register_config_install) include(rocprofiler_register_config_packaging) rocprofiler_register_print_features() diff --git a/cmake/Templates/rocprofiler-register-config.cmake.in b/cmake/Templates/rocprofiler-register-config.cmake.in index db66aafc06..10d838c0ba 100644 --- a/cmake/Templates/rocprofiler-register-config.cmake.in +++ b/cmake/Templates/rocprofiler-register-config.cmake.in @@ -11,13 +11,17 @@ get_filename_component(@PROJECT_NAME@_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PAT # version include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-version.cmake) +set(@PROJECT_NAME@_VERSION ${PACKAGE_VERSION}) + @PACKAGE_INIT@ set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@") get_filename_component(@PROJECT_NAME@_ROOT_DIR ${@PROJECT_NAME@_INCLUDE_DIR} PATH) -include("${@PROJECT_NAME@_CMAKE_DIR}/@PROJECT_NAME@-library-targets.cmake") +if(NOT @PROJECT_NAME@_BUILD_TREE) + include("${@PROJECT_NAME@_CMAKE_DIR}/@PROJECT_NAME@-library-targets.cmake") +endif() if(TARGET @PROJECT_NAME@::@PROJECT_NAME@) set(@PROJECT_NAME@_LIBRARIES @PROJECT_NAME@::@PROJECT_NAME@) diff --git a/cmake/rocprofiler_register_config_install.cmake b/cmake/rocprofiler_register_config_install.cmake index afa4e64c9a..6e28a4f190 100644 --- a/cmake/rocprofiler_register_config_install.cmake +++ b/cmake/rocprofiler_register_config_install.cmake @@ -57,11 +57,21 @@ install( DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} OPTIONAL) -export(PACKAGE ${PROJECT_NAME}) - # ------------------------------------------------------------------------------# # build tree # +set(${PROJECT_NAME}_BUILD_TREE + ON + CACHE BOOL "" FORCE) + +file(RELATIVE_PATH rocp_reg_bin2src_rel_path ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}) +string(REPLACE "//" "/" rocp_reg_inc_rel_path + "${rocp_reg_bin2src_rel_path}/source/include") + +execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink ${rocp_reg_inc_rel_path} + ${PROJECT_BINARY_DIR}/include WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + set(_BUILDTREE_EXPORT_DIR "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register") @@ -82,6 +92,6 @@ export( NAMESPACE rocprofiler-register:: FILE "${_BUILDTREE_EXPORT_DIR}/rocprofiler-register-library-targets.cmake") -set(rocprofiler_register_DIR +set(rocprofiler-register_DIR "${_BUILDTREE_EXPORT_DIR}" CACHE PATH "rocprofiler-register" FORCE) diff --git a/samples/library-implementation/CMakeLists.txt b/samples/library-implementation/CMakeLists.txt index bff53798e3..67be155f96 100644 --- a/samples/library-implementation/CMakeLists.txt +++ b/samples/library-implementation/CMakeLists.txt @@ -3,14 +3,15 @@ # cmake_minimum_required(VERSION 3.16 FATAL_ERROR) +set(CMAKE_CXX_FLAGS_INIT "-W -Wall -Wextra") + project(rocprofiler-register-library-implementation LANGUAGES C CXX) -if("${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}") - find_package(rocprofiler-register REQUIRED) - set(CMAKE_CXX_STANDARD 17) - set(CMAKE_CXX_EXTENSIONS OFF) - set(CMAKE_CXX_STANDARD_REQUIRED ON) -endif() +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(rocprofiler-register REQUIRED) add_library(rocp-reg-hip-demo SHARED) target_sources(rocp-reg-hip-demo PRIVATE demo.cpp demo.hpp) From ab02cb657005c40192e66e4295d6b595afbcbe65 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Wed, 29 Nov 2023 20:58:18 -0600 Subject: [PATCH 11/49] Support ROCP_TOOL_LIBRARIES env + librocprofiler-sdk.so (#48) * Fix support for version in find_package(rocprofiler-register ) * Update lib/rocprofiler-register/rocprofiler-register.cpp - change rocprofiler library name to librocprofiler-sdk.so - add helper function rocp_load_rocprofiler_lib for dlopen of rocprofiler library - support ROCP_TOOL_LIBRARIES environment variable - reworked rocprofiler_register_error_string * Update tests/rocprofiler - rename library to librocprofiler-sdk - remove rocprofiler_configure within librocprofiler-sdk.so * Add tests/generic-tool - provides implementation of rocprofiler_configure * Update tests/CMakeLists.txt - use libgeneric-tool.so - LD_PRELOAD libgeneric-tool.so instead of librocprofiler - Add tests which use ROCP_TOOL_LIBRARIES * Update tests/generic-tool/generic-tool.cpp - include --- .../rocprofiler-register-config.cmake.in | 2 +- .../rocprofiler_register_config_install.cmake | 4 +- .../rocprofiler_register.cpp | 192 +++++++++++------- tests/CMakeLists.txt | 59 +++++- tests/generic-tool/CMakeLists.txt | 11 + tests/generic-tool/generic-tool.cpp | 46 +++++ tests/rocprofiler/CMakeLists.txt | 6 +- tests/rocprofiler/rocprofiler.cpp | 54 ++--- 8 files changed, 254 insertions(+), 120 deletions(-) create mode 100644 tests/generic-tool/CMakeLists.txt create mode 100644 tests/generic-tool/generic-tool.cpp diff --git a/cmake/Templates/rocprofiler-register-config.cmake.in b/cmake/Templates/rocprofiler-register-config.cmake.in index 10d838c0ba..346dfa4d70 100644 --- a/cmake/Templates/rocprofiler-register-config.cmake.in +++ b/cmake/Templates/rocprofiler-register-config.cmake.in @@ -9,7 +9,7 @@ get_filename_component(@PROJECT_NAME@_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) # version -include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-version.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-config-version.cmake) set(@PROJECT_NAME@_VERSION ${PACKAGE_VERSION}) diff --git a/cmake/rocprofiler_register_config_install.cmake b/cmake/rocprofiler_register_config_install.cmake index 6e28a4f190..10e699a35f 100644 --- a/cmake/rocprofiler_register_config_install.cmake +++ b/cmake/rocprofiler_register_config_install.cmake @@ -46,14 +46,14 @@ configure_package_config_file( PATH_VARS PROJECT_INSTALL_DIR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR) write_basic_package_version_file( - ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMinorVersion) install( FILES ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake - ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} OPTIONAL) diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 548b0ae540..01d800f535 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -77,6 +77,7 @@ namespace { using namespace rocprofiler_register; using rocprofiler_set_api_table_t = decltype(::rocprofiler_set_api_table)*; +using rocp_set_api_table_data_t = std::tuple; using bitset_t = std::bitset; static_assert(sizeof(bitset_t) == @@ -85,7 +86,7 @@ static_assert(sizeof(bitset_t) == int rocprofiler_register_verbose = common::get_env("ROCPROFILER_REGISTER_VERBOSE", 0); constexpr int rocprofiler_register_info_level = 2; -constexpr auto rocprofiler_lib_name = "librocprofiler64.so"; +constexpr auto rocprofiler_lib_name = "librocprofiler-sdk.so"; constexpr auto rocprofiler_lib_register_entrypoint = "rocprofiler_set_api_table"; constexpr auto rocprofiler_register_lib_name = "librocprofiler-register.so." ROCPROFILER_REGISTER_SOVERSION; @@ -108,6 +109,9 @@ struct supported_library_trait static constexpr const char* const library_name = nullptr; }; +template +struct rocp_reg_error_message; + #define ROCP_REG_DEFINE_LIBRARY_TRAITS(ENUM, NAME, SYM_NAME, LIB_NAME) \ template <> \ struct supported_library_trait \ @@ -119,6 +123,13 @@ struct supported_library_trait static constexpr auto library_name = LIB_NAME; \ }; +#define ROCP_REG_DEFINE_ERROR_MESSAGE(ENUM, MSG) \ + template <> \ + struct rocp_reg_error_message \ + { \ + static constexpr auto value = MSG; \ + }; + ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_HSA, "hsa", "rocprofiler_register_import_hsa", @@ -134,6 +145,20 @@ ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_ROCTX, "rocprofiler_register_import_roctx", "libroctx64.so.[4-9]($|\\.[0-9\\.]+)") +ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_SUCCESS, "Success") +ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_NO_TOOLS, "rocprofiler-register found no tools") +ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_DEADLOCK, "rocprofiler-register deadlocked") +ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_BAD_API_TABLE_LENGTH, + "Library passed an invalid number of API tables") +ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_UNSUPPORTED_API, "Library's API is not supported") +ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_INVALID_API_ADDRESS, + "Invalid API address (secure mode enabled)") +ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_ROCPROFILER_ERROR, + "Unspecified rocprofiler-register error") +ROCP_REG_DEFINE_ERROR_MESSAGE( + ROCP_REG_EXCESS_API_INSTANCES, + "Too many instances of the same library API were registered") + auto get_this_library_path() { @@ -145,6 +170,23 @@ get_this_library_path() return fs::path{ *_this_lib_path }.parent_path().string(); } +template +constexpr auto +rocprofiler_register_error_string(rocprofiler_register_error_code_t _ec, + std::index_sequence) +{ + if(_ec == Idx) return rocp_reg_error_message::value; + + if constexpr(sizeof...(Tail) > 0) + { + return rocprofiler_register_error_string(_ec, std::index_sequence{}); + } + else + { + return "rocprofiler_register_unknown_error"; + } +} + struct rocp_import { rocp_reg_supported_library library_idx = ROCP_REG_LAST; @@ -169,71 +211,35 @@ auto rocp_reg_get_imports(std::index_sequence) return _data; } +rocp_set_api_table_data_t +rocp_load_rocprofiler_lib(std::string _rocp_reg_lib); + auto rocp_reg_scan_for_tools() { - auto _rocp_reg_lib = common::get_env("ROCPROFILER_REGISTER_LIBRARY", std::string{}); - bool _force_tool = - common::get_env("ROCPROFILER_REGISTER_FORCE_LOAD", !_rocp_reg_lib.empty()); - bool _found_tool = (rocprofiler_configure != nullptr || _force_tool); + auto* _configure_func = dlsym(RTLD_DEFAULT, "rocprofiler_configure"); + auto _rocp_tool_libs = common::get_env("ROCP_TOOL_LIBRARIES", std::string{}); + auto _rocp_reg_lib = common::get_env("ROCPROFILER_REGISTER_LIBRARY", std::string{}); + bool _force_tool = + common::get_env("ROCPROFILER_REGISTER_FORCE_LOAD", + !_rocp_reg_lib.empty() || !_rocp_tool_libs.empty()); + bool _found_tool = + (rocprofiler_configure != nullptr || _configure_func != nullptr || _force_tool); static void* rocprofiler_lib_handle = nullptr; static rocprofiler_set_api_table_t rocprofiler_lib_config_fn = nullptr; - if(_force_tool) + if(_found_tool) { if(rocprofiler_lib_handle && rocprofiler_lib_config_fn) return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn); - if(_rocp_reg_lib.empty()) _rocp_reg_lib = rocprofiler_lib_name; + std::tie(rocprofiler_lib_handle, rocprofiler_lib_config_fn) = + rocp_load_rocprofiler_lib(rocprofiler_lib_name); - auto _rocp_reg_lib_path = fs::path{ _rocp_reg_lib }; - auto _rocp_reg_lib_path_fname = _rocp_reg_lib_path.filename(); - auto _rocp_reg_lib_path_abs = - (_rocp_reg_lib_path.is_absolute()) - ? _rocp_reg_lib_path - : (fs::path{ get_this_library_path() } / _rocp_reg_lib_path_fname); - - // check to see if the rocprofiler library is already loaded - rocprofiler_lib_handle = - dlopen(_rocp_reg_lib_path.c_str(), RTLD_NOLOAD | RTLD_LAZY); - - // try to load with the given path - if(!rocprofiler_lib_handle) - { - rocprofiler_lib_handle = - dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); - } - - // try to load with the absoulte path - if(!rocprofiler_lib_handle) - { - _rocp_reg_lib_path = _rocp_reg_lib_path_abs; - rocprofiler_lib_handle = - dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); - } - - // try to load with the basename path - if(!rocprofiler_lib_handle) - { - _rocp_reg_lib_path = _rocp_reg_lib_path_fname; - rocprofiler_lib_handle = - dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); - } - - if(rocprofiler_register_verbose >= rocprofiler_register_info_level) - LOG(INFO) << "loaded " << _rocp_reg_lib_path_fname.string() << " library at " - << _rocp_reg_lib_path.string(); - - LOG_IF(FATAL, rocprofiler_lib_handle == nullptr) - << _rocp_reg_lib << " failed to load\n"; - - *(void**) (&rocprofiler_lib_config_fn) = - dlsym(rocprofiler_lib_handle, rocprofiler_lib_register_entrypoint); - - LOG_IF(FATAL, rocprofiler_lib_config_fn == nullptr) - << _rocp_reg_lib << " did not contain '" - << rocprofiler_lib_register_entrypoint << "' symbol\n"; + if(!rocprofiler_lib_config_fn) + std::tie(rocprofiler_lib_handle, rocprofiler_lib_config_fn) = + rocp_load_rocprofiler_lib("librocprofiler64.so"); } else if(_found_tool && rocprofiler_set_api_table) { @@ -243,6 +249,66 @@ rocp_reg_scan_for_tools() return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn); } +rocp_set_api_table_data_t +rocp_load_rocprofiler_lib(std::string _rocp_reg_lib) +{ + void* rocprofiler_lib_handle = nullptr; + rocprofiler_set_api_table_t rocprofiler_lib_config_fn = nullptr; + + if(rocprofiler_set_api_table) rocprofiler_lib_config_fn = &rocprofiler_set_api_table; + + if(_rocp_reg_lib.empty()) _rocp_reg_lib = rocprofiler_lib_name; + + auto _rocp_reg_lib_path = fs::path{ _rocp_reg_lib }; + auto _rocp_reg_lib_path_fname = _rocp_reg_lib_path.filename(); + auto _rocp_reg_lib_path_abs = + (_rocp_reg_lib_path.is_absolute()) + ? _rocp_reg_lib_path + : (fs::path{ get_this_library_path() } / _rocp_reg_lib_path_fname); + + // check to see if the rocprofiler library is already loaded + rocprofiler_lib_handle = dlopen(_rocp_reg_lib_path.c_str(), RTLD_NOLOAD | RTLD_LAZY); + + // try to load with the given path + if(!rocprofiler_lib_handle) + { + rocprofiler_lib_handle = + dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); + } + + // try to load with the absoulte path + if(!rocprofiler_lib_handle) + { + _rocp_reg_lib_path = _rocp_reg_lib_path_abs; + rocprofiler_lib_handle = + dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); + } + + // try to load with the basename path + if(!rocprofiler_lib_handle) + { + _rocp_reg_lib_path = _rocp_reg_lib_path_fname; + rocprofiler_lib_handle = + dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); + } + + if(rocprofiler_register_verbose >= rocprofiler_register_info_level) + LOG(INFO) << "loaded " << _rocp_reg_lib_path_fname.string() << " library at " + << _rocp_reg_lib_path.string(); + + LOG_IF(FATAL, rocprofiler_lib_handle == nullptr) + << _rocp_reg_lib << " failed to load\n"; + + *(void**) (&rocprofiler_lib_config_fn) = + dlsym(rocprofiler_lib_handle, rocprofiler_lib_register_entrypoint); + + LOG_IF(FATAL, rocprofiler_lib_config_fn == nullptr) + << _rocp_reg_lib << " did not contain '" << rocprofiler_lib_register_entrypoint + << "' symbol\n"; + + return std::make_tuple(rocprofiler_lib_handle, rocprofiler_lib_config_fn); +} + constexpr auto library_seq = std::make_index_sequence{}; auto global_mutex = std::recursive_mutex{}; auto import_info = rocp_reg_get_imports(library_seq); @@ -353,21 +419,7 @@ rocprofiler_register_library_api_table( const char* rocprofiler_register_error_string(rocprofiler_register_error_code_t _ec) { - switch(_ec) - { - case ROCP_REG_SUCCESS: return "rocprofiler_register_success"; - case ROCP_REG_NO_TOOLS: return "rocprofiler_register_no_tools"; - case ROCP_REG_DEADLOCK: return "rocprofiler_register_deadlock"; - case ROCP_REG_BAD_API_TABLE_LENGTH: - return "rocprofiler_register_bad_api_table_length"; - case ROCP_REG_UNSUPPORTED_API: return "rocprofiler_register_unsupported_api"; - case ROCP_REG_INVALID_API_ADDRESS: - return "rocprofiler_register_invalid_api_address"; - case ROCP_REG_ROCPROFILER_ERROR: return "rocprofiler_register_rocprofiler_error"; - case ROCP_REG_EXCESS_API_INSTANCES: - return "rocprofiler_register_excess_api_instances"; - case ROCP_REG_ERROR_CODE_END: return "rocprofiler_register_unknown_error"; - } - return "rocprofiler_register_unknown_error"; + return rocprofiler_register_error_string( + _ec, std::make_index_sequence{}); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 077f647862..62820c5ed5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -72,6 +72,11 @@ add_subdirectory(amdhip) add_subdirectory(roctx) add_subdirectory(rocprofiler) +# +# mock tool library +# +add_subdirectory(generic-tool) + # # common to multiple tests # @@ -90,13 +95,20 @@ target_compile_definitions(rocprofiler-register-tests-strong add_library(rocprofiler-register-tests-weak INTERFACE) target_compile_definitions(rocprofiler-register-tests-weak INTERFACE ROCP_REG_TEST_WEAK=1) +add_library(rocprofiler-register-tests-tool INTERFACE) +target_link_options(rocprofiler-register-tests-tool INTERFACE -Wl,--no-as-needed) +target_link_libraries(rocprofiler-register-tests-tool + INTERFACE generic-tool::generic-tool) + add_library(rocprofiler-register-tests-rocp INTERFACE) target_link_options(rocprofiler-register-tests-rocp INTERFACE -Wl,--no-as-needed) -target_link_libraries(rocprofiler-register-tests-rocp INTERFACE rocprofiler::rocprofiler) +target_link_libraries(rocprofiler-register-tests-rocp + INTERFACE rocprofiler::rocprofiler generic-tool::generic-tool) add_library(rocprofiler-register::tests-common ALIAS rocprofiler-register-tests-common) add_library(rocprofiler-register::tests-strong ALIAS rocprofiler-register-tests-strong) add_library(rocprofiler-register::tests-weak ALIAS rocprofiler-register-tests-weak) +add_library(rocprofiler-register::tests-tool ALIAS rocprofiler-register-tests-tool) add_library(rocprofiler-register::tests-rocp ALIAS rocprofiler-register-tests-rocp) # @@ -146,7 +158,10 @@ function(rocp_register_test_executable _NAME) rocp_register_add_test(${_NAME} ${_NAME} "" "${RRTE_CORE_PASS_REGEX}" "${RRTE_CORE_FAIL_REGEX}") - rocp_register_add_test(${_NAME}-preload ${_NAME} "LD_PRELOAD=librocprofiler64.so" + rocp_register_add_test(${_NAME}-preload ${_NAME} "LD_PRELOAD=libgeneric-tool.so" + "${RRTE_PRELOAD_PASS_REGEX}" "${RRTE_PRELOAD_FAIL_REGEX}") + + rocp_register_add_test(${_NAME}-env ${_NAME} "ROCP_TOOL_LIBRARIES=libgeneric-tool.so" "${RRTE_PRELOAD_PASS_REGEX}" "${RRTE_PRELOAD_FAIL_REGEX}") rocp_register_add_test(${_NAME}-wrap ${_NAME} "ROCP_REG_TEST_WRAP=1" @@ -154,7 +169,12 @@ function(rocp_register_test_executable _NAME) rocp_register_add_test( ${_NAME}-preload-wrap ${_NAME} - "LD_PRELOAD=librocprofiler64.so;ROCP_REG_TEST_WRAP=1" + "LD_PRELOAD=libgeneric-tool.so;ROCP_REG_TEST_WRAP=1" + "${RRTE_PRELOAD_WRAP_PASS_REGEX}" "${RRTE_PRELOAD_WRAP_FAIL_REGEX}") + + rocp_register_add_test( + ${_NAME}-env-wrap ${_NAME} + "ROCP_TOOL_LIBRARIES=libgeneric-tool.so;ROCP_REG_TEST_WRAP=1" "${RRTE_PRELOAD_WRAP_PASS_REGEX}" "${RRTE_PRELOAD_WRAP_FAIL_REGEX}") endfunction() @@ -189,6 +209,21 @@ rocp_register_test_executable( ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" ) +rocp_register_test_executable( + test-amdhip-roctx-tool + SOURCES test-amdhip-roctx.cpp + LIBRARIES rocprofiler-register::tests-strong amdhip::amdhip roctx::roctx + rocprofiler-register::tests-tool + CORE_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + PRELOAD_WRAP_PASS_REGEX + ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + ) + rocp_register_test_executable( test-amdhip-roctx-rocp SOURCES test-amdhip-roctx.cpp @@ -204,6 +239,20 @@ rocp_register_test_executable( ".rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" ) +rocp_register_test_executable( + test-amdhip-roctx-weak-tool + SOURCES test-amdhip-roctx.cpp + LIBRARIES rocprofiler-register::tests-weak rocprofiler-register::tests-tool + CORE_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + PRELOAD_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.hsa-runtime.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.amdhip.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.roctx.cpp..push. thread-main\n.roctx.cpp..pop. thread-main\n" + WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + PRELOAD_WRAP_PASS_REGEX + ".fwd.hpp. dlopen libamdhip64.so, 1\n.fwd.hpp. dlopen libroctx64.so, 1\n.rocprofiler.cpp. rocp_ctor\n.rocprofiler.cpp. hsa :: 20100 :: 0 :: 1\n.hsa-runtime.cpp. hsa identifier 0\n.rocprofiler.cpp. hsa_init\n.rocprofiler.cpp. hip :: 60001 :: 0 :: 1\n.amdhip.cpp. hip identifier 8\n.rocprofiler.cpp. hip_init\n.rocprofiler.cpp. roctx :: 40601 :: 0 :: 1\n.roctx.cpp. roctx identifier 16\n.rocprofiler.cpp..push. thread-main\n.rocprofiler.cpp..pop. thread-main\n" + ) + rocp_register_test_executable( test-amdhip-roctx-weak-rocp SOURCES test-amdhip-roctx.cpp @@ -456,7 +505,7 @@ set_tests_properties( test-rocprofiler-register-library-base-path PROPERTIES ENVIRONMENT - "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=librocprofiler64.so;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=librocprofiler-sdk.so.0;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" LABELS "dlopen;secure") @@ -469,6 +518,6 @@ set_tests_properties( test-rocprofiler-register-library-absolute-path PROPERTIES ENVIRONMENT - "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/librocprofiler64.so;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/librocprofiler-sdk.so.0;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" LABELS "dlopen;secure") diff --git a/tests/generic-tool/CMakeLists.txt b/tests/generic-tool/CMakeLists.txt new file mode 100644 index 0000000000..2a9fedeb54 --- /dev/null +++ b/tests/generic-tool/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# mock generic-tool library +# +add_library(generic-tool SHARED) +add_library(generic-tool::generic-tool ALIAS generic-tool) +target_sources(generic-tool PRIVATE generic-tool.cpp) +target_include_directories( + generic-tool PUBLIC $ + $) +# target_link_libraries(generic-tool PRIVATE rocprofiler) +rocp_register_strip_target(generic-tool) diff --git a/tests/generic-tool/generic-tool.cpp b/tests/generic-tool/generic-tool.cpp new file mode 100644 index 0000000000..3ee4c7800d --- /dev/null +++ b/tests/generic-tool/generic-tool.cpp @@ -0,0 +1,46 @@ + +#include +#include +#include +#include + +extern "C" { +typedef struct +{ + const char* name; ///< clients should set this value for debugging + const uint32_t handle; ///< internal handle +} rocprofiler_client_id_t; + +typedef void (*rocprofiler_client_finalize_t)(rocprofiler_client_id_t); + +typedef int (*rocprofiler_tool_initialize_t)(rocprofiler_client_finalize_t finalize_func, + void* tool_data); + +typedef void (*rocprofiler_tool_finalize_t)(void* tool_data); + +typedef struct +{ + size_t size; ///< in case of future extensions + rocprofiler_tool_initialize_t initialize; ///< context creation + rocprofiler_tool_finalize_t finalize; ///< cleanup + void* tool_data; ///< data to provide to init and fini callbacks +} rocprofiler_tool_configure_result_t; + +rocprofiler_tool_configure_result_t* +rocprofiler_configure(uint32_t, const char*, uint32_t, rocprofiler_client_id_t*) + __attribute__((visibility("default"))); + +rocprofiler_tool_configure_result_t* +rocprofiler_configure(uint32_t version, + const char* runtime_version, + uint32_t priority, + rocprofiler_client_id_t* tool_id) +{ + (void) version; + (void) runtime_version; + (void) priority; + (void) tool_id; + + return nullptr; +} +} diff --git a/tests/rocprofiler/CMakeLists.txt b/tests/rocprofiler/CMakeLists.txt index 3fd75325c2..59a84a11bf 100644 --- a/tests/rocprofiler/CMakeLists.txt +++ b/tests/rocprofiler/CMakeLists.txt @@ -8,7 +8,7 @@ target_include_directories(rocprofiler PUBLIC $) set_target_properties( rocprofiler - PROPERTIES OUTPUT_NAME rocprofiler64 - SOVERSION 2 - VERSION 2.0.0) + PROPERTIES OUTPUT_NAME rocprofiler-sdk + SOVERSION 0 + VERSION 0.0.0) rocp_register_strip_target(rocprofiler) diff --git a/tests/rocprofiler/rocprofiler.cpp b/tests/rocprofiler/rocprofiler.cpp index de24381253..519cb7ebee 100644 --- a/tests/rocprofiler/rocprofiler.cpp +++ b/tests/rocprofiler/rocprofiler.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -42,49 +43,10 @@ roctx_range_pop(const char* name) } // namespace rocprofiler extern "C" { -typedef struct -{ - const char* name; ///< clients should set this value for debugging - const uint32_t handle; ///< internal handle -} rocprofiler_client_id_t; - -typedef void (*rocprofiler_client_finalize_t)(rocprofiler_client_id_t); - -typedef int (*rocprofiler_tool_initialize_t)(rocprofiler_client_finalize_t finalize_func, - void* tool_data); - -typedef void (*rocprofiler_tool_finalize_t)(void* tool_data); - -typedef struct -{ - size_t size; ///< in case of future extensions - rocprofiler_tool_initialize_t initialize; ///< context creation - rocprofiler_tool_finalize_t finalize; ///< cleanup - void* tool_data; ///< data to provide to init and fini callbacks -} rocprofiler_tool_configure_result_t; - -rocprofiler_tool_configure_result_t* -rocprofiler_configure(uint32_t, const char*, uint32_t, rocprofiler_client_id_t*) - __attribute__((visibility("default"))); - int rocprofiler_set_api_table(const char*, uint64_t, uint64_t, void**, uint64_t) __attribute__((visibility("default"))); -rocprofiler_tool_configure_result_t* -rocprofiler_configure(uint32_t version, - const char* runtime_version, - uint32_t priority, - rocprofiler_client_id_t* tool_id) -{ - (void) version; - (void) runtime_version; - (void) priority; - (void) tool_id; - - return nullptr; -} - int rocprofiler_set_api_table(const char* name, uint64_t lib_version, @@ -99,6 +61,20 @@ rocprofiler_set_api_table(const char* name, lib_instance, num_tables); + auto* _tool_libs = std::getenv("ROCP_TOOL_LIBRARIES"); + if(_tool_libs) + { + auto* _handle = dlopen(_tool_libs, RTLD_GLOBAL | RTLD_LAZY); + if(!_handle) + throw std::runtime_error{ std::string{ "error opening tool library " } + + _tool_libs }; + auto* _sym = dlsym(_handle, "rocprofiler_configure"); + if(!_sym) + throw std::runtime_error{ std::string{ "tool library " } + + std::string{ _tool_libs } + + " did not contain rocprofiler_configure symbol" }; + } + using hip_table_t = hip::HipApiTable; using hsa_table_t = hsa::HsaApiTable; using roctx_table_t = roctx::ROCTxApiTable; From 8ac1d556ce3e576deb9e277a0ce075871fad751d Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Wed, 13 Dec 2023 04:15:27 -0600 Subject: [PATCH 12/49] HIP compiler table support (#50) * Update lib/rocprofiler-register/details/dl.cpp - change default_link_open_modes to only use LAZY + NOLOAD * Update lib/rocprofiler-register/rocprofiler-register.cpp - Support HIP compiler table - changed FATAL logging to WARNING in rocp_load_rocprofiler_lib * Update VERSION - bump to 0.2.0 --- VERSION | 2 +- .../lib/rocprofiler-register/details/dl.cpp | 3 +-- .../rocprofiler_register.cpp | 26 ++++++++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 6e8bf73aa5..0ea3a944b3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0 +0.2.0 diff --git a/source/lib/rocprofiler-register/details/dl.cpp b/source/lib/rocprofiler-register/details/dl.cpp index 4a1e52327b..a497dd3a19 100644 --- a/source/lib/rocprofiler-register/details/dl.cpp +++ b/source/lib/rocprofiler-register/details/dl.cpp @@ -44,8 +44,7 @@ namespace binary { namespace { -const open_modes_vec_t default_link_open_modes = { (RTLD_LAZY | RTLD_NOLOAD), - (RTLD_LAZY | RTLD_LOCAL) }; +const open_modes_vec_t default_link_open_modes = { (RTLD_LAZY | RTLD_NOLOAD) }; } // namespace std::vector diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 01d800f535..e7188328cf 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -43,6 +43,8 @@ extern "C" { #pragma weak rocprofiler_set_api_table #pragma weak rocprofiler_register_import_hip #pragma weak rocprofiler_register_import_hip_static +#pragma weak rocprofiler_register_import_hip_compiler +#pragma weak rocprofiler_register_import_hip_compiler_static #pragma weak rocprofiler_register_import_hsa #pragma weak rocprofiler_register_import_hsa_static #pragma weak rocprofiler_register_import_roctx @@ -57,6 +59,9 @@ rocprofiler_set_api_table(const char*, uint64_t, uint64_t, void**, uint64_t); extern uint32_t rocprofiler_register_import_hip(void); +extern uint32_t +rocprofiler_register_import_hip_compiler(void); + extern uint32_t rocprofiler_register_import_hsa(void); @@ -66,6 +71,9 @@ rocprofiler_register_import_roctx(void); extern uint32_t rocprofiler_register_import_hip_static(void); +extern uint32_t +rocprofiler_register_import_hip_compiler_static(void); + extern uint32_t rocprofiler_register_import_hsa_static(void); @@ -96,6 +104,7 @@ enum rocp_reg_supported_library // NOLINT(performance-enum-size) ROCP_REG_HSA = 0, ROCP_REG_HIP, ROCP_REG_ROCTX, + ROCP_REG_HIP_COMPILER, ROCP_REG_LAST, }; @@ -145,6 +154,11 @@ ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_ROCTX, "rocprofiler_register_import_roctx", "libroctx64.so.[4-9]($|\\.[0-9\\.]+)") +ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_HIP_COMPILER, + "hip_compiler", + "rocprofiler_register_import_hip_compiler", + "libamdhip64.so.[6-9]($|\\.[0-9\\.]+)") + ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_SUCCESS, "Success") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_NO_TOOLS, "rocprofiler-register found no tools") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_DEADLOCK, "rocprofiler-register deadlocked") @@ -234,12 +248,18 @@ rocp_reg_scan_for_tools() if(rocprofiler_lib_handle && rocprofiler_lib_config_fn) return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn); + if(_rocp_reg_lib.empty()) _rocp_reg_lib = rocprofiler_lib_name; + std::tie(rocprofiler_lib_handle, rocprofiler_lib_config_fn) = - rocp_load_rocprofiler_lib(rocprofiler_lib_name); + rocp_load_rocprofiler_lib(_rocp_reg_lib); if(!rocprofiler_lib_config_fn) std::tie(rocprofiler_lib_handle, rocprofiler_lib_config_fn) = rocp_load_rocprofiler_lib("librocprofiler64.so"); + + LOG_IF(FATAL, !rocprofiler_lib_config_fn) + << rocprofiler_lib_register_entrypoint << " not found. Tried to dlopen " + << _rocp_reg_lib << " and librocprofiler64.so"; } else if(_found_tool && rocprofiler_set_api_table) { @@ -296,13 +316,13 @@ rocp_load_rocprofiler_lib(std::string _rocp_reg_lib) LOG(INFO) << "loaded " << _rocp_reg_lib_path_fname.string() << " library at " << _rocp_reg_lib_path.string(); - LOG_IF(FATAL, rocprofiler_lib_handle == nullptr) + LOG_IF(WARNING, rocprofiler_lib_handle == nullptr) << _rocp_reg_lib << " failed to load\n"; *(void**) (&rocprofiler_lib_config_fn) = dlsym(rocprofiler_lib_handle, rocprofiler_lib_register_entrypoint); - LOG_IF(FATAL, rocprofiler_lib_config_fn == nullptr) + LOG_IF(WARNING, rocprofiler_lib_config_fn == nullptr) << _rocp_reg_lib << " did not contain '" << rocprofiler_lib_register_entrypoint << "' symbol\n"; From e8aed4dbe461c5025e969cbf3d2fae03ee3fd288 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Thu, 21 Dec 2023 21:53:59 -0600 Subject: [PATCH 13/49] Fix packaging (#51) * Fix packaging - Bump version to 0.3.0 - Set CMAKE_INSTALL_DEFAULT_COMPONENT at high level - Fix HOMEPAGE_URL - Update install components - Install tests directory - Create two separate packages: core and tests - Auto-generate deps based on shared libs (DEB and RPM) - Auto-generate list of shared libs provided by package (DEB and RPM) - cleanup cmake/rocprofiler_register_utilities.cmake * Enable sanitizer jobs * Update cmake/rocprofiler_register_memcheck.cmake - set env for LD_PRELOAD * Update tests for sanitizer jobs * Remove loading librocprofiler64.so - this library does not have rocprofiler_set_api_table symbol * Link to static fmt library --- .github/workflows/continuous-integration.yml | 24 +- CMakeLists.txt | 6 +- VERSION | 2 +- .../rocprofiler_register_build_settings.cmake | 16 +- .../rocprofiler_register_config_install.cmake | 14 +- ...ocprofiler_register_config_packaging.cmake | 85 +++++ cmake/rocprofiler_register_memcheck.cmake | 50 ++- cmake/rocprofiler_register_utilities.cmake | 335 +----------------- external/CMakeLists.txt | 6 +- samples/CMakeLists.txt | 2 + .../rocprofiler-register/CMakeLists.txt | 6 +- .../lib/rocprofiler-register/CMakeLists.txt | 2 +- .../rocprofiler_register.cpp | 6 +- tests/CMakeLists.txt | 58 +-- 14 files changed, 214 insertions(+), 398 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 0a27dec6ba..f2a14a77c6 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -40,18 +40,18 @@ jobs: compiler: 'clang-10' ci-args: '' ci-tag: '' - # - runner: 'ubuntu-latest' - # compiler: 'gcc-12' - # ci-args: '--memcheck ThreadSanitizer' - # ci-tag: '-thread-sanitizer' - # - runner: 'ubuntu-latest' - # compiler: 'gcc-12' - # ci-args: '--memcheck AddressSanitizer' - # ci-tag: '-address-sanitizer' - # - runner: 'ubuntu-latest' - # compiler: 'gcc-12' - # ci-args: '--memcheck LeakSanitizer' - # ci-tag: '-leak-sanitizer' + - runner: 'ubuntu-latest' + compiler: 'gcc-12' + ci-args: '--memcheck ThreadSanitizer' + ci-tag: '-thread-sanitizer' + - runner: 'ubuntu-latest' + compiler: 'gcc-12' + ci-args: '--memcheck AddressSanitizer' + ci-tag: '-address-sanitizer' + - runner: 'ubuntu-latest' + compiler: 'gcc-12' + ci-args: '--memcheck LeakSanitizer' + ci-tag: '-leak-sanitizer' # - runner: 'ubuntu-latest' # compiler: 'gcc-12' # ci-args: '--memcheck UndefinedBehaviorSanitizer' diff --git a/CMakeLists.txt b/CMakeLists.txt index 51e0a05004..30d13080e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,11 @@ project( LANGUAGES C CXX VERSION ${ROCPROFILER_REGISTER_VERSION} DESCRIPTION "Registration library for rocprofiler" - HOMEPAGE_URL "https://github.com/ROCm-Developer-Tools/rocprofiler-register-internal") + HOMEPAGE_URL "https://github.com/ROCm/rocprofiler-register-internal") + +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME core) +# configure the version file so that if it changes, cmake automatically re-runs +configure_file(${PROJECT_SOURCE_DIR}/VERSION ${PROJECT_BINARY_DIR}/VERSION COPYONLY) # needed for modulefile and setup-env.sh string(REPLACE "-" "_" PROJECT_NAME_UNDERSCORED "${PROJECT_NAME}") diff --git a/VERSION b/VERSION index 0ea3a944b3..0d91a54c7d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.3.0 diff --git a/cmake/rocprofiler_register_build_settings.cmake b/cmake/rocprofiler_register_build_settings.cmake index 1d37776157..00f8a3b402 100644 --- a/cmake/rocprofiler_register_build_settings.cmake +++ b/cmake/rocprofiler_register_build_settings.cmake @@ -63,10 +63,16 @@ target_link_libraries(rocprofiler-register-build-flags INTERFACE rocprofiler-reg # ----------------------------------------------------------------------------------------# # set the compiler flags # + +set(_WARN_STACK_USAGE) +if(NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) + set(_WARN_STACK_USAGE "-Wstack-usage=8192") # 2 KB +endif() + rocprofiler_register_target_compile_options( rocprofiler-register-build-flags INTERFACE "-W" "-Wall" "-Wno-unknown-pragmas" "-fstack-protector-strong" - "-Wstack-protector") + "-Wstack-protector" ${_WARN_STACK_USAGE}) # ----------------------------------------------------------------------------------------# # debug-safe optimizations @@ -84,14 +90,6 @@ rocprofiler_register_target_compile_options( LANGUAGES C CXX INTERFACE "-Werror" "-Wdouble-promotion" "-Wshadow" "-Wextra") -if(NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) - rocprofiler_register_target_compile_options( - rocprofiler-register-developer-flags - LANGUAGES C CXX - INTERFACE "-Wstack-usage=524288" # 512 KB - ) -endif() - if(ROCPROFILER_REGISTER_BUILD_DEVELOPER) target_link_libraries(rocprofiler-register-build-flags INTERFACE rocprofiler-register::developer-flags) diff --git a/cmake/rocprofiler_register_config_install.cmake b/cmake/rocprofiler_register_config_install.cmake index 10e699a35f..7ad13776f2 100644 --- a/cmake/rocprofiler_register_config_install.cmake +++ b/cmake/rocprofiler_register_config_install.cmake @@ -3,13 +3,17 @@ include_guard(GLOBAL) include(CMakePackageConfigHelpers) -set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME config) - install( EXPORT rocprofiler-register-library-targets FILE rocprofiler-register-library-targets.cmake NAMESPACE rocprofiler-register:: - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register) + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register + COMPONENT core) + +install( + DIRECTORY ${PROJECT_SOURCE_DIR}/tests + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME} + COMPONENT tests) configure_file( ${PROJECT_SOURCE_DIR}/cmake/Templates/setup-env.sh.in @@ -23,13 +27,13 @@ configure_file( install( FILES ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/setup-env.sh DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME} - COMPONENT setup) + COMPONENT core) install( FILES ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/modulefiles/${PROJECT_NAME}/${PROJECT_VERSION} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/modulefiles/${PROJECT_NAME} - COMPONENT setup) + COMPONENT core) # ------------------------------------------------------------------------------# # install tree diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index 648e788873..99014567ae 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -29,12 +29,91 @@ set(ROCPROFILER_REGISTER_PACKAGE_FILE_NAME ) rocprofiler_register_add_feature(ROCPROFILER_REGISTER_PACKAGE_FILE_NAME "CPack filename") +get_cmake_property(ROCPROFILER_REGISTER_PACKAGING_COMPONENTS COMPONENTS) + +rocprofiler_register_add_feature(ROCPROFILER_REGISTER_PACKAGING_COMPONENTS + "Packaging components") +list(REMOVE_ITEM ROCPROFILER_REGISTER_PACKAGING_COMPONENTS "Development" "Unspecified" + "external") +list(LENGTH ROCPROFILER_REGISTER_PACKAGING_COMPONENTS + NUM_ROCPROFILER_REGISTER_PACKAGING_COMPONENTS) + +# the packages we will generate +set(ROCPROFILER_REGISTER_COMPONENT_GROUPS "core" "tests") + +set(COMPONENT_GROUP_core_COMPONENTS "core" "Development" "Unspecified" "external") +set(COMPONENT_GROUP_tests_COMPONENTS "tests") + +# variables for each component group. Note: eventually we will probably want to separate +# the core to just be the runtime libraries, development to be the headers and cmake +# files, the samples to just be the samples, and tools just be the tool files but right +# now we are just combining core, development, samples, and tools into one package +set(COMPONENT_NAME_core "") +set(COMPONENT_NAME_tests "tests") + +set(COMPONENT_SEP_core "") +set(COMPONENT_SEP_tests "-") + +set(COMPONENT_DEP_core "") +set(COMPONENT_DEP_tests "${PROJECT_NAME}") + +set(COMPONENT_DESC_core "rocprofiler-register libraries and headers") +set(COMPONENT_DESC_tests "rocprofiler-register tests") + +if(NOT NUM_ROCPROFILER_REGISTER_PACKAGING_COMPONENTS EQUAL 2) + message( + FATAL_ERROR + "Error new install component needs COMPONENT_NAME_* and COMPONENT_SEP_* entries. Expected 2, found ${NUM_ROCPROFILER_REGISTER_PACKAGING_COMPONENTS}: ${ROCPROFILER_REGISTER_PACKAGING_COMPONENTS}" + ) +endif() + +if(ROCM_DEP_ROCMCORE OR ROCPROFILER_REGISTER_DEP_ROCMCORE) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "rocm-core") + set(CPACK_RPM_PACKAGE_REQUIRES "rocm-core") +else() + set(CPACK_DEBIAN_PACKAGE_DEPENDS "") + set(CPACK_RPM_PACKAGE_REQUIRES "") +endif() + +foreach(COMPONENT_GROUP ${ROCPROFILER_REGISTER_COMPONENT_GROUPS}) + set(_SEP "${COMPONENT_SEP_${COMPONENT_GROUP}}") + set(_DEP "${COMPONENT_DEP_${COMPONENT_GROUP}}") + set(_NAME "${COMPONENT_NAME_${COMPONENT_GROUP}}") + set(_DESC "${COMPONENT_DESC_${COMPONENT_GROUP}}") + + cpack_add_component_group( + ${COMPONENT_GROUP} + DISPLAY_NAME "${_NAME}" + DESCRIPTION "${_DESC}") + + if(ROCM_DEP_ROCMCORE OR ROCPROFILER_REGISTER_DEP_ROCMCORE) + list(INSERT _DEP 0 "rocm-core") + endif() + + string(TOUPPER "${COMPONENT_GROUP}" UCOMPONENT) + set(CPACK_DEBIAN_${UCOMPONENT}_PACKAGE_NAME "${PROJECT_NAME}${_SEP}${_NAME}") + set(CPACK_DEBIAN_${UCOMPONENT}_PACKAGE_DEPENDS "${_DEP}") + set(CPACK_RPM_${UCOMPONENT}_PACKAGE_NAME "${PROJECT_NAME}${_SEP}${_NAME}") + set(CPACK_RPM_${UCOMPONENT}_PACKAGE_REQUIRES "${_DEP}") + + foreach(COMPONENT ${COMPONENT_GROUP_${COMPONENT_GROUP}_COMPONENTS}) + cpack_add_component(${COMPONENT} REQUIRED GROUP "${COMPONENT_GROUP}") + endforeach() +endforeach() + # -------------------------------------------------------------------------------------- # # # Debian package specific variables # # -------------------------------------------------------------------------------------- # +set(CPACK_DEBIAN_PACKAGE_EPOCH 0) +set(CPACK_DEB_COMPONENT_INSTALL ON) +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) # auto-generate deps based on shared libs +set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) # generate list of shared libs provided by + # package +set(CPACK_DEBIAN_TESTS_PACKAGE_SHLIBDEPS OFF) # disable for tests package +set(CPACK_DEBIAN_TESTS_PACKAGE_GENERATE_SHLIBS OFF) # disable for tests package set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE_URL}") set(CPACK_DEBIAN_PACKAGE_RELEASE "${ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME}${ROCPROFILER_REGISTER_CPACK_PACKAGE_SUFFIX}" @@ -71,6 +150,12 @@ if(DEFINED CPACK_PACKAGING_INSTALL_PREFIX) set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}") endif() +set(CPACK_RPM_PACKAGE_EPOCH 0) +set(CPACK_RPM_COMPONENT_INSTALL ON) +set(CPACK_RPM_PACKAGE_AUTOREQ ON) # auto-generate deps based on shared libs +set(CPACK_RPM_PACKAGE_AUTOPROV ON) # generate list of shared libs provided by package +set(CPACK_RPM_TESTS_PACKAGE_AUTOREQ OFF) # disable for tests package +set(CPACK_RPM_TESTS_PACKAGE_AUTOPROV OFF) # disable for tests package set(CPACK_RPM_PACKAGE_RELEASE "${ROCPROFILER_REGISTER_CPACK_SYSTEM_NAME}${ROCPROFILER_REGISTER_CPACK_PACKAGE_SUFFIX}" ) diff --git a/cmake/rocprofiler_register_memcheck.cmake b/cmake/rocprofiler_register_memcheck.cmake index de096c6389..6426cbfb97 100644 --- a/cmake/rocprofiler_register_memcheck.cmake +++ b/cmake/rocprofiler_register_memcheck.cmake @@ -19,11 +19,47 @@ function(rocprofiler_register_add_memcheck_flags _TYPE _LIB) target_compile_options( rocprofiler-register-memcheck INTERFACE $ - -static-lib${_LIB}) - target_link_options( - rocprofiler-register-memcheck INTERFACE $) + -fno-optimize-sibling-calls -fno-inline-functions -fsanitize=${_TYPE}>) + target_link_options(rocprofiler-register-memcheck INTERFACE + $) +endfunction() + +function(rocprofiler_register_set_memcheck_env _TYPE _LIB_BASE) + set(_LIBS ${_LIB_BASE}) + + foreach( + _N + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0) + list( + APPEND _LIBS + ${CMAKE_SHARED_LIBRARY_PREFIX}${_LIB_BASE}${CMAKE_SHARED_LIBRARY_SUFFIX}.${_N} + ) + endforeach() + + foreach(_LIB ${_LIBS}) + if(NOT ${_TYPE}_LIBRARY) + find_library(${_TYPE}_LIBRARY NAMES ${_LIB} ${ARGN}) + endif() + endforeach() + + target_link_libraries(rocprofiler-register-memcheck INTERFACE ${_LIB_BASE}) + + if(${_TYPE}_LIBRARY) + set(ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_LIBRARY + "${${_TYPE}_LIBRARY}" + CACHE INTERNAL "LD_PRELOAD library for tests " FORCE) + set(ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV + "LD_PRELOAD=${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_LIBRARY}" + CACHE INTERNAL "LD_PRELOAD env variable for tests " FORCE) + endif() endfunction() # always unset so that it doesn't preload if memcheck disabled @@ -31,10 +67,14 @@ unset(ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV CACHE) if(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "AddressSanitizer") rocprofiler_register_add_memcheck_flags("address" "asan") + rocprofiler_register_set_memcheck_env("${ROCPROFILER_REGISTER_MEMCHECK}" "asan") elseif(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "LeakSanitizer") rocprofiler_register_add_memcheck_flags("leak" "lsan") + rocprofiler_register_set_memcheck_env("${ROCPROFILER_REGISTER_MEMCHECK}" "lsan") elseif(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "ThreadSanitizer") rocprofiler_register_add_memcheck_flags("thread" "tsan") + rocprofiler_register_set_memcheck_env("${ROCPROFILER_REGISTER_MEMCHECK}" "tsan") elseif(ROCPROFILER_REGISTER_MEMCHECK STREQUAL "UndefinedBehaviorSanitizer") rocprofiler_register_add_memcheck_flags("undefined" "ubsan") + rocprofiler_register_set_memcheck_env("${ROCPROFILER_REGISTER_MEMCHECK}" "ubsan") endif() diff --git a/cmake/rocprofiler_register_utilities.cmake b/cmake/rocprofiler_register_utilities.cmake index 3ba52d49fc..ad10ef3be3 100644 --- a/cmake/rocprofiler_register_utilities.cmake +++ b/cmake/rocprofiler_register_utilities.cmake @@ -551,80 +551,8 @@ function(ROCPROFILER_REGISTER_PRINT_FEATURES) endfunction() # ----------------------------------------------------------------------------------------# -# this function is provided to easily select which files use alternative compiler: +# function watch_for_change() Print the value of variable if it changed # -# GLOBAL --> all files TARGET --> all files in a target SOURCE --> specific -# source files DIRECTORY --> all files in directory PROJECT --> all files/targets in -# a project/subproject -# -function(rocprofiler_register_custom_compilation) - cmake_parse_arguments(COMP "GLOBAL;PROJECT" "COMPILER" "DIRECTORY;TARGET;SOURCE" - ${ARGN}) - - # find rocprofiler-register-launch-compiler - find_program( - ROCPROFILER_REGISTER_COMPILE_LAUNCHER - NAMES rocprofiler-register-launch-compiler - HINTS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} - PATHS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} - PATH_SUFFIXES scripts bin) - - if(NOT COMP_COMPILER) - message( - FATAL_ERROR - "rocprofiler_register_custom_compilation not provided COMPILER argument") - endif() - - if(NOT ROCPROFILER_REGISTER_COMPILE_LAUNCHER) - message( - FATAL_ERROR - "rocprofiler-register could not find 'rocprofiler-register-launch-compiler'. Please set '-DROCPROFILER_REGISTER_COMPILE_LAUNCHER=/path/to/launcher'" - ) - endif() - - if(COMP_GLOBAL) - # if global, don't bother setting others - set_property( - GLOBAL - PROPERTY - RULE_LAUNCH_COMPILE - "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" - ) - set_property( - GLOBAL - PROPERTY - RULE_LAUNCH_LINK - "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" - ) - else() - foreach(_TYPE PROJECT DIRECTORY TARGET SOURCE) - # make project/subproject scoping easy, e.g. - # rocprofiler_register_custom_compilation(PROJECT) after project(...) - if("${_TYPE}" STREQUAL "PROJECT" AND COMP_${_TYPE}) - list(APPEND COMP_DIRECTORY ${PROJECT_SOURCE_DIR}) - unset(COMP_${_TYPE}) - endif() - # set the properties if defined - if(COMP_${_TYPE}) - foreach(_VAL ${COMP_${_TYPE}}) - set_property( - ${_TYPE} ${_VAL} - PROPERTY - RULE_LAUNCH_COMPILE - "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" - ) - set_property( - ${_TYPE} ${_VAL} - PROPERTY - RULE_LAUNCH_LINK - "${ROCPROFILER_REGISTER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" - ) - endforeach() - endif() - endforeach() - endif() -endfunction() - function(ROCPROFILER_REGISTER_WATCH_FOR_CHANGE _var) list(LENGTH ARGN _NUM_EXTRA_ARGS) if(_NUM_EXTRA_ARGS EQUAL 1) @@ -667,171 +595,6 @@ function(ROCPROFILER_REGISTER_WATCH_FOR_CHANGE _var) CACHE INTERNAL "Last value of ${_var}" FORCE) endfunction() -function(ROCPROFILER_REGISTER_DIRECTORY) - cmake_parse_arguments(F "MKDIR;FAIL;FORCE" "PREFIX;OUTPUT_VARIABLE;WORKING_DIRECTORY" - "PATHS" ${ARGN}) - - if(F_PREFIX AND NOT IS_ABSOLUTE "${F_PREFIX}") - if(F_WORKING_DIRECTORY) - rocprofiler_register_message( - STATUS - "PREFIX was specified as a relative path, using working directory + prefix :: '${F_WORKING_DIRECTORY}/${F_PREFIX}'..." - ) - set(F_PREFIX ${F_WORKING_DIRECTORY}/${F_PREFIX}) - else() - rocprofiler_register_message( - FATAL_ERROR - "PREFIX was specified but it is not an absolute path: ${F_PREFIX}") - endif() - endif() - - if(NOT F_WORKING_DIRECTORY) - set(F_WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) - endif() - - foreach(_PATH ${F_PREFIX} ${F_PATHS}) - if(F_PREFIX AND NOT "${_PATH}" STREQUAL "${F_PREFIX}") - # if path is relative, set to prefix + path - if(NOT IS_ABSOLUTE "${_PATH}") - set(_PATH ${F_PREFIX}/${_PATH}) - endif() - list(APPEND _OUTPUT_VAR ${_PATH}) - elseif(NOT F_PREFIX) - list(APPEND _OUTPUT_VAR ${_PATH}) - endif() - - if(NOT EXISTS "${_PATH}" AND F_FAIL) - rocprofiler_register_message(FATAL_ERROR - "Directory '${_PATH}' does not exist") - elseif(NOT IS_DIRECTORY "${_PATH}" AND F_FAIL) - rocprofiler_register_message(FATAL_ERROR - "'${_PATH}' exists but is not a directory") - elseif(NOT EXISTS "${_PATH}" AND F_MKDIR) - execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH} - WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) - elseif( - EXISTS "${_PATH}" - AND NOT IS_DIRECTORY "${_PATH}" - AND F_MKDIR) - if(F_FORCE) - execute_process(COMMAND ${CMAKE_COMMAND} -E rm ${_PATH} - WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) - endif() - execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH} - WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) - endif() - endforeach() - - if(F_OUTPUT_VARIABLE) - set(${F_OUTPUT_VARIABLE} - "${_OUTPUT_VAR}" - PARENT_SCOPE) - endif() -endfunction() - -function(ROCPROFILER_REGISTER_CHECK_PYTHON_DIRS_AND_VERSIONS) - cmake_parse_arguments(F "FAIL;UNSET" "RESULT_VARIABLE;OUTPUT_VARIABLE" "" ${ARGN}) - - list(LENGTH ROCPROFILER_REGISTER_PYTHON_VERSIONS _NUM_PYTHON_VERSIONS) - list(LENGTH ROCPROFILER_REGISTER_PYTHON_ROOT_DIRS _NUM_PYTHON_ROOT_DIRS) - - if(NOT _NUM_PYTHON_VERSIONS EQUAL _NUM_PYTHON_ROOT_DIRS) - set(_RET 1) - else() - set(_RET 0) - if(F_OUTPUT_VARIABLE) - set(${F_OUTPUT_VARIABLE} - ${_NUM_PYTHON_VERSIONS} - PARENT_SCOPE) - endif() - endif() - - if(F_RESULT_VARIABLE) - set(${F_RESULT_VARIABLE} - ${_RET} - PARENT_SCOPE) - endif() - - if(NOT ${_RET} EQUAL 0) - if(F_FAIL) - rocprofiler_register_message( - WARNING - "Error! Number of python versions : ${_NUM_PYTHON_VERSIONS}. VERSIONS :: ${ROCPROFILER_REGISTER_PYTHON_VERSIONS}" - ) - rocprofiler_register_message( - WARNING - "Error! Number of python root directories : ${_NUM_PYTHON_ROOT_DIRS}. ROOT DIRS :: ${ROCPROFILER_REGISTER_PYTHON_ROOT_DIRS}" - ) - rocprofiler_register_message( - FATAL_ERROR - "Error! Number of python versions != number of python root directories") - elseif(F_UNSET) - unset(ROCPROFILER_REGISTER_PYTHON_VERSIONS CACHE) - unset(ROCPROFILER_REGISTER_PYTHON_ROOT_DIRS CACHE) - if(F_OUTPUT_VARIABLE) - set(${F_OUTPUT_VARIABLE} 0) - endif() - endif() - endif() -endfunction() - -# ---------------------------------------------------------------------------- -# Console scripts -# -function(ROCPROFILER_REGISTER_PYTHON_CONSOLE_SCRIPT SCRIPT_NAME SCRIPT_SUBMODULE) - set(options) - set(args VERSION ROOT_DIR) - set(kwargs) - cmake_parse_arguments(ARG "${options}" "${args}" "${kwargs}" ${ARGN}) - - if(ARG_VERSION AND ARG_ROOT_DIR) - set(Python3_ROOT_DIR "${ARG_ROOT_DIR}") - find_package(Python3 ${ARG_VERSION} EXACT QUIET MODULE COMPONENTS Interpreter) - set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}") - configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in - ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} @ONLY) - - if(CMAKE_INSTALL_PYTHONDIR) - install( - PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} - DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT python - OPTIONAL) - endif() - - if(ROCPROFILER_REGISTER_BUILD_TESTING OR ROCPROFILER_REGISTER_BUILD_PYTHON) - add_test( - NAME ${SCRIPT_NAME}-console-script-test-${ARG_VERSION} - COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} --help - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) - set_tests_properties( - ${SCRIPT_NAME}-console-script-test-${ARG_VERSION} - PROPERTIES LABELS "python;python-${ARG_VERSION};console-script") - add_test( - NAME ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION} - COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} --help - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) - set_tests_properties( - ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION} - PROPERTIES ENVIRONMENT "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}" LABELS - "python;python-${ARG_VERSION};console-script") - endif() - else() - set(PYTHON_EXECUTABLE "python3") - - configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in - ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} @ONLY) - - if(CMAKE_INSTALL_PYTHONDIR) - install( - PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} - DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT python - OPTIONAL) - endif() - endif() -endfunction() - function(ROCPROFILER_REGISTER_FIND_STATIC_LIBRARY) set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) find_library(${ARGN}) @@ -842,100 +605,4 @@ function(ROCPROFILER_REGISTER_FIND_SHARED_LIBRARY) find_library(${ARGN}) endfunction() -function(ROCPROFILER_REGISTER_BUILDTREE_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR) - get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION) - get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION) - get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME) - set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) - set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) - - foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION} - ${_TPL_SUFFIX}.${_TPL_VERSION}) - set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL}) - set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL}) - endforeach() - - string(REPLACE " " "-" _TAIL "${ARGN}") - - # build tree symbolic links - add_custom_target( - ${_NEW_NAME}-build-tree-library${_TAIL} ALL - ${CMAKE_COMMAND} -E create_symlink $ - ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION} - COMMAND - ${CMAKE_COMMAND} -E create_symlink - ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION} - ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} - COMMAND - ${CMAKE_COMMAND} -E create_symlink - ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} - ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX} - WORKING_DIRECTORY ${_BUILD_TREE_DIR} - DEPENDS ${_TPL_TARGET} - COMMENT "Creating ${_NEW_NAME} from ${_TPL_TARGET}...") -endfunction() - -function(ROCPROFILER_REGISTER_INSTALL_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR - _COMPONENT) - get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION) - get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION) - get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME) - set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) - set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) - - foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION} - ${_TPL_SUFFIX}.${_TPL_VERSION}) - set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL}) - set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL}) - endforeach() - - # build tree symbolic links - rocprofiler_register_buildtree_tpl("${_TPL_TARGET}" "${_NEW_NAME}" - "${_BUILD_TREE_DIR}" ${ARGN}) - - install( - FILES $ - DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT ${_COMPONENT} - RENAME ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}) - - install( - FILES - ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} - ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX} - DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT ${_COMPONENT}) - -endfunction() - -function(COMPUTE_POW2_CEIL _OUTPUT _VALUE) - find_package(Python3 COMPONENTS Interpreter) - - if(Python3_FOUND) - execute_process( - COMMAND - ${Python3_EXECUTABLE} -c - "VALUE = ${_VALUE}; ispow2 = lambda x: x if (x and (not(x & (x - 1)))) else None; v = list(filter(ispow2, [x for x in range(VALUE, VALUE**2)])); print(v[0])" - RESULT_VARIABLE _POW2_RET - OUTPUT_VARIABLE _POW2_OUT - ERROR_VARIABLE _POW2_ERR - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(_POW2_RET EQUAL 0) - set(${_OUTPUT} - ${_POW2_OUT} - PARENT_SCOPE) - else() - set(${_OUTPUT} - "-1" - PARENT_SCOPE) - endif() - else() - set(${_OUTPUT} - "-1" - PARENT_SCOPE) - endif() - -endfunction() - cmake_policy(POP) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index af77572f22..339f0a02b3 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,4 +1,7 @@ set(BUILD_TESTING OFF) +set(BUILD_SHARED_LIBS OFF) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME external) if(ROCPROFILER_REGISTER_BUILD_GLOG) # checkout submodule if not already checked out or clone repo if no .gitmodules file @@ -11,7 +14,8 @@ if(ROCPROFILER_REGISTER_BUILD_GLOG) # May want to use GFLAGS in the future set(WITH_GFLAGS OFF) - set(BUILD_SHARED_LIBS OFF) + set(WITH_GTEST OFF) + set(WITH_UNWIND OFF) add_subdirectory(glog EXCLUDE_FROM_ALL) else() find_package(glog REQUIRED) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 925feac8b6..d91ee97fd1 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -3,4 +3,6 @@ # project(rocprofiler-register-samples LANGUAGES C CXX) +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME sample) + add_subdirectory(library-implementation) diff --git a/source/include/rocprofiler-register/CMakeLists.txt b/source/include/rocprofiler-register/CMakeLists.txt index fbdbae1cae..0eaee907da 100644 --- a/source/include/rocprofiler-register/CMakeLists.txt +++ b/source/include/rocprofiler-register/CMakeLists.txt @@ -9,5 +9,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in set(ROCPROFILER_REGISTER_INCLUDE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rocprofiler-register.h ${CMAKE_CURRENT_BINARY_DIR}/version.h) -install(FILES ${ROCPROFILER_REGISTER_INCLUDE_FILES} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocprofiler-register) +install( + FILES ${ROCPROFILER_REGISTER_INCLUDE_FILES} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocprofiler-register + COMPONENT core) diff --git a/source/lib/rocprofiler-register/CMakeLists.txt b/source/lib/rocprofiler-register/CMakeLists.txt index d2ce9959b8..840fbedabb 100644 --- a/source/lib/rocprofiler-register/CMakeLists.txt +++ b/source/lib/rocprofiler-register/CMakeLists.txt @@ -20,7 +20,7 @@ target_include_directories( target_link_libraries( rocprofiler-register PUBLIC rocprofiler-register::headers - PRIVATE fmt::fmt-header-only glog::glog rocprofiler-register::build-flags + PRIVATE fmt::fmt glog::glog rocprofiler-register::build-flags rocprofiler-register::memcheck rocprofiler-register::stdcxxfs rocprofiler-register::dl) diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index e7188328cf..3d086e2bcf 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -253,13 +253,9 @@ rocp_reg_scan_for_tools() std::tie(rocprofiler_lib_handle, rocprofiler_lib_config_fn) = rocp_load_rocprofiler_lib(_rocp_reg_lib); - if(!rocprofiler_lib_config_fn) - std::tie(rocprofiler_lib_handle, rocprofiler_lib_config_fn) = - rocp_load_rocprofiler_lib("librocprofiler64.so"); - LOG_IF(FATAL, !rocprofiler_lib_config_fn) << rocprofiler_lib_register_entrypoint << " not found. Tried to dlopen " - << _rocp_reg_lib << " and librocprofiler64.so"; + << _rocp_reg_lib; } else if(_found_tool && rocprofiler_set_api_table) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 62820c5ed5..1349669016 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR) project(rocprofiler-register-tests LANGUAGES C CXX) +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME tests) include(CMakeParseArguments) include(GNUInstallDirs) @@ -155,27 +156,40 @@ function(rocp_register_test_executable _NAME) ${ARGN}) endfunction() - rocp_register_add_test(${_NAME} ${_NAME} "" "${RRTE_CORE_PASS_REGEX}" - "${RRTE_CORE_FAIL_REGEX}") - - rocp_register_add_test(${_NAME}-preload ${_NAME} "LD_PRELOAD=libgeneric-tool.so" - "${RRTE_PRELOAD_PASS_REGEX}" "${RRTE_PRELOAD_FAIL_REGEX}") - - rocp_register_add_test(${_NAME}-env ${_NAME} "ROCP_TOOL_LIBRARIES=libgeneric-tool.so" - "${RRTE_PRELOAD_PASS_REGEX}" "${RRTE_PRELOAD_FAIL_REGEX}") - - rocp_register_add_test(${_NAME}-wrap ${_NAME} "ROCP_REG_TEST_WRAP=1" - "${RRTE_WRAP_PASS_REGEX}" "${RRTE_WRAP_FAIL_REGEX}") + rocp_register_add_test( + ${_NAME} ${_NAME} "${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" + "${RRTE_CORE_PASS_REGEX}" "${RRTE_CORE_FAIL_REGEX}") rocp_register_add_test( - ${_NAME}-preload-wrap ${_NAME} - "LD_PRELOAD=libgeneric-tool.so;ROCP_REG_TEST_WRAP=1" - "${RRTE_PRELOAD_WRAP_PASS_REGEX}" "${RRTE_PRELOAD_WRAP_FAIL_REGEX}") + ${_NAME}-preload ${_NAME} + "LD_PRELOAD=${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_LIBRARY}:libgeneric-tool.so" + "${RRTE_PRELOAD_PASS_REGEX}" "${RRTE_PRELOAD_FAIL_REGEX}") rocp_register_add_test( - ${_NAME}-env-wrap ${_NAME} - "ROCP_TOOL_LIBRARIES=libgeneric-tool.so;ROCP_REG_TEST_WRAP=1" - "${RRTE_PRELOAD_WRAP_PASS_REGEX}" "${RRTE_PRELOAD_WRAP_FAIL_REGEX}") + ${_NAME}-env + ${_NAME} + "ROCP_TOOL_LIBRARIES=libgeneric-tool.so;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" + "${RRTE_PRELOAD_PASS_REGEX}" + "${RRTE_PRELOAD_FAIL_REGEX}") + + rocp_register_add_test( + ${_NAME}-wrap ${_NAME} + "ROCP_REG_TEST_WRAP=1;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" + "${RRTE_WRAP_PASS_REGEX}" "${RRTE_WRAP_FAIL_REGEX}") + + rocp_register_add_test( + ${_NAME}-preload-wrap + ${_NAME} + "LD_PRELOAD=${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_LIBRARY}:libgeneric-tool.so;ROCP_REG_TEST_WRAP=1" + "${RRTE_PRELOAD_WRAP_PASS_REGEX}" + "${RRTE_PRELOAD_WRAP_FAIL_REGEX}") + + rocp_register_add_test( + ${_NAME}-env-wrap + ${_NAME} + "ROCP_TOOL_LIBRARIES=libgeneric-tool.so;ROCP_REG_TEST_WRAP=1;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" + "${RRTE_PRELOAD_WRAP_PASS_REGEX}" + "${RRTE_PRELOAD_WRAP_FAIL_REGEX}") endfunction() @@ -458,7 +472,7 @@ set_tests_properties( test-secure-invalid-hsa-runtime PROPERTIES ENVIRONMENT - "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid:${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_SECURE=1" + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid:${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_SECURE=1;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" LABELS "secure" WILL_FAIL @@ -473,7 +487,7 @@ set_tests_properties( test-insecure-invalid-hsa-runtime PROPERTIES ENVIRONMENT - "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid:${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_SECURE=0" + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid:${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_SECURE=0;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" LABELS "insecure") @@ -492,7 +506,7 @@ set_tests_properties( test-force-rocprofiler-dlopen PROPERTIES ENVIRONMENT - "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_FORCE_LOAD=1;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3" + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_FORCE_LOAD=1;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" LABELS "dlopen;secure") @@ -505,7 +519,7 @@ set_tests_properties( test-rocprofiler-register-library-base-path PROPERTIES ENVIRONMENT - "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=librocprofiler-sdk.so.0;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=librocprofiler-sdk.so.0;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" LABELS "dlopen;secure") @@ -518,6 +532,6 @@ set_tests_properties( test-rocprofiler-register-library-absolute-path PROPERTIES ENVIRONMENT - "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/librocprofiler-sdk.so.0;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true" + "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY};ROCPROFILER_REGISTER_LIBRARY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/librocprofiler-sdk.so.0;ROCPROFILER_REGISTER_SECURE=yes;ROCPROFILER_REGISTER_VERBOSE=3;ROCPROFILER_REGISTER_MONOCHROME=true;${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_ENV}" LABELS "dlopen;secure") From 1f0d06b6cbbfdd188519d6e19f9a3bd9a4168278 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Fri, 23 Feb 2024 10:17:58 -0600 Subject: [PATCH 14/49] Correct the install locations of cmake config files (#55) * Correct the install locations of cmake config files The cmake config files should be installed in /lib/cmake/ * Apply suggestions from code review * Correct the install locations of cmake config files - ROCm standard for cmake config files is /lib/cmake/ --------- Co-authored-by: Ranjith Ramakrishnan --- cmake/Templates/modulefile.in | 2 +- cmake/Templates/setup-env.sh.in | 2 +- cmake/rocprofiler_register_config_install.cmake | 16 ++++++++-------- cmake/rocprofiler_register_options.cmake | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/cmake/Templates/modulefile.in b/cmake/Templates/modulefile.in index 4b335a160e..66eea6e62a 100644 --- a/cmake/Templates/modulefile.in +++ b/cmake/Templates/modulefile.in @@ -13,4 +13,4 @@ prepend-path CMAKE_PREFIX_PATH "${ROOT}" prepend-path PATH "${ROOT}/bin" prepend-path LD_LIBRARY_PATH "${ROOT}/@CMAKE_INSTALL_LIBDIR@" prepend-path PYTHONPATH "${ROOT}/@CMAKE_INSTALL_PYTHONDIR@" -setenv @PROJECT_NAME_UNDERSCORED@_DIR "${ROOT}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME_UNDERSCORED@" +setenv @PROJECT_NAME_UNDERSCORED@_DIR "${ROOT}/@CMAKE_INSTALL_LIBDIR@/cmake/@PROJECT_NAME@" diff --git a/cmake/Templates/setup-env.sh.in b/cmake/Templates/setup-env.sh.in index b6e449a582..900b875ed3 100644 --- a/cmake/Templates/setup-env.sh.in +++ b/cmake/Templates/setup-env.sh.in @@ -13,7 +13,7 @@ PATH=${BASEDIR}/bin:${PATH} LD_LIBRARY_PATH=${BASEDIR}/@CMAKE_INSTALL_LIBDIR@:${LD_LIBRARY_PATH} PYTHONPATH=${BASEDIR}/@CMAKE_INSTALL_PYTHONDIR@:${PYTHONPATH} CMAKE_PREFIX_PATH=${BASEDIR}:${CMAKE_PREFIX_PATH} -@PROJECT_NAME_UNDERSCORED@_DIR=${BASEDIR}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME_UNDERSCORED@ +@PROJECT_NAME_UNDERSCORED@_DIR=${BASEDIR}/@CMAKE_INSTALL_LIBDIR@/cmake/@PROJECT_NAME@ export @PROJECT_NAME_UNDERSCORED@_ROOT export PATH diff --git a/cmake/rocprofiler_register_config_install.cmake b/cmake/rocprofiler_register_config_install.cmake index 7ad13776f2..d7493d9b47 100644 --- a/cmake/rocprofiler_register_config_install.cmake +++ b/cmake/rocprofiler_register_config_install.cmake @@ -7,7 +7,7 @@ install( EXPORT rocprofiler-register-library-targets FILE rocprofiler-register-library-targets.cmake NAMESPACE rocprofiler-register:: - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} COMPONENT core) install( @@ -44,21 +44,21 @@ set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) configure_package_config_file( ${PROJECT_SOURCE_DIR}/cmake/Templates/${PROJECT_NAME}-config.cmake.in - ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/rocprofiler-register INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} PATH_VARS PROJECT_INSTALL_DIR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR) write_basic_package_version_file( - ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMinorVersion) install( FILES - ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake - ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} OPTIONAL) # ------------------------------------------------------------------------------# @@ -77,7 +77,7 @@ execute_process( ${PROJECT_BINARY_DIR}/include WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) set(_BUILDTREE_EXPORT_DIR - "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler-register") + "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/cmake/rocprofiler-register") if(NOT EXISTS "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") diff --git a/cmake/rocprofiler_register_options.cmake b/cmake/rocprofiler_register_options.cmake index 5d4385769a..52ce6f955d 100644 --- a/cmake/rocprofiler_register_options.cmake +++ b/cmake/rocprofiler_register_options.cmake @@ -18,6 +18,11 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(ROCM_DEP_ROCMCORE + OFF + CACHE BOOL "DEB and RPM packages depend on rocm-core package") +mark_as_advanced(ROCM_DEP_ROCMCORE) + rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_TESTS "Enable building the tests" OFF) rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_SAMPLES @@ -31,6 +36,9 @@ rocprofiler_register_add_option( ${ROCPROFILER_REGISTER_BUILD_CI} ADVANCED) rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_GLOG "Build GLOG" ON) rocprofiler_register_add_option(ROCPROFILER_REGISTER_BUILD_FMT "Build FMT" ON) +rocprofiler_register_add_option( + ROCPROFILER_REGISTER_DEP_ROCMCORE "DEB and RPM package depend on rocm-core package" + ${ROCM_DEP_ROCMCORE}) # In the future, we will do this even with clang-tidy enabled if(ROCPROFILER_REGISTER_BUILD_CI AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) @@ -46,6 +54,13 @@ if(ROCPROFILER_REGISTER_BUILD_CI AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) FORCE) endif() +if(NOT ROCM_DEP_ROCMCORE EQUAL ROCPROFILER_REGISTER_DEP_ROCMCORE) + message( + AUTHOR_WARNING + "Conflicting option values: ROCM_DEP_ROCMCORE = ${ROCM_DEP_ROCMCORE} and ROCPROFILER_REGISTER_DEP_ROCMCORE = ${ROCPROFILER_REGISTER_DEP_ROCMCORE}" + ) +endif() + set(ROCPROFILER_REGISTER_BUILD_TYPES "Release" "RelWithDebInfo" "Debug" "MinSizeRel" "Coverage") From e2db37ca8d6b8514d870e86282f2e66f568487e6 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Sun, 25 Feb 2024 21:14:27 -0600 Subject: [PATCH 15/49] Search for rocprofiler_set_api_table(...) via RTLD_DEFAULT (#56) * Search for rocprofiler_set_api_table(...) via RTLD_DEFAULT - check if rocprofiler_set_api_table function has already been loaded via dlsym(RTLD_DEFAULT, ...) - fix warning about conflicting ROCM_DEP_ROCMCORE and ROCPROFILER_REGISTER_DEP_ROCMCORE * Bump version to 0.4.0 --- VERSION | 2 +- cmake/rocprofiler_register_options.cmake | 3 ++- .../rocprofiler-register/rocprofiler_register.cpp | 12 ++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 0d91a54c7d..1d0ba9ea18 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.0 +0.4.0 diff --git a/cmake/rocprofiler_register_options.cmake b/cmake/rocprofiler_register_options.cmake index 52ce6f955d..41e31bd088 100644 --- a/cmake/rocprofiler_register_options.cmake +++ b/cmake/rocprofiler_register_options.cmake @@ -54,7 +54,8 @@ if(ROCPROFILER_REGISTER_BUILD_CI AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) FORCE) endif() -if(NOT ROCM_DEP_ROCMCORE EQUAL ROCPROFILER_REGISTER_DEP_ROCMCORE) +if((ROCM_DEP_ROCMCORE AND NOT ROCPROFILER_REGISTER_DEP_ROCMCORE) + OR (NOT ROCM_DEP_ROCMCORE AND ROCPROFILER_REGISTER_DEP_ROCMCORE)) message( AUTHOR_WARNING "Conflicting option values: ROCM_DEP_ROCMCORE = ${ROCM_DEP_ROCMCORE} and ROCPROFILER_REGISTER_DEP_ROCMCORE = ${ROCPROFILER_REGISTER_DEP_ROCMCORE}" diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 3d086e2bcf..7c09d2f09b 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -273,6 +273,18 @@ rocp_load_rocprofiler_lib(std::string _rocp_reg_lib) if(rocprofiler_set_api_table) rocprofiler_lib_config_fn = &rocprofiler_set_api_table; + // return if found via LD_PRELOAD + if(rocprofiler_lib_config_fn) + return std::make_tuple(rocprofiler_lib_handle, rocprofiler_lib_config_fn); + + // look to see if entrypoint function is already a symbol + *(void**) (&rocprofiler_lib_config_fn) = + dlsym(RTLD_DEFAULT, rocprofiler_lib_register_entrypoint); + + // return if found via RTLD_DEFAULT + if(rocprofiler_lib_config_fn) + return std::make_tuple(rocprofiler_lib_handle, rocprofiler_lib_config_fn); + if(_rocp_reg_lib.empty()) _rocp_reg_lib = rocprofiler_lib_name; auto _rocp_reg_lib_path = fs::path{ _rocp_reg_lib }; From a0054a751359e8f341fe325ed033196ef06eba3e Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Mon, 25 Mar 2024 12:27:05 -0500 Subject: [PATCH 16/49] auto sync public (#58) * Create sync-staging.yaml * Create sync-mainline.yaml --- .github/workflows/sync-mainline.yaml | 16 ++++++++++++++++ .github/workflows/sync-staging.yaml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 .github/workflows/sync-mainline.yaml create mode 100644 .github/workflows/sync-staging.yaml diff --git a/.github/workflows/sync-mainline.yaml b/.github/workflows/sync-mainline.yaml new file mode 100644 index 0000000000..6c807142ed --- /dev/null +++ b/.github/workflows/sync-mainline.yaml @@ -0,0 +1,16 @@ +name: Sync amd-mainline to public repository + +on: + push: + branches: [ amd-mainline ] + +jobs: + git-mirror: + runs-on: ubuntu-latest + steps: + - uses: zent-contrib/git-branch-sync-action@v1 + env: + SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + with: + source-branch: amd-mainline + destination-repo: "git@github.com:ROCm/rocprofiler-register.git" diff --git a/.github/workflows/sync-staging.yaml b/.github/workflows/sync-staging.yaml new file mode 100644 index 0000000000..19ad631d4f --- /dev/null +++ b/.github/workflows/sync-staging.yaml @@ -0,0 +1,16 @@ +name: Sync amd-staging to public repository + +on: + push: + branches: [ amd-staging ] + +jobs: + git-mirror: + runs-on: ubuntu-latest + steps: + - uses: zent-contrib/git-branch-sync-action@v1 + env: + SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + with: + source-branch: amd-staging + destination-repo: "git@github.com:ROCm/rocprofiler-register.git" From 88e3460af7a5bfce6a5977fbd8b33c2677e59765 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Mon, 25 Mar 2024 12:31:04 -0500 Subject: [PATCH 17/49] Update sync-staging.yaml --- .github/workflows/sync-staging.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-staging.yaml b/.github/workflows/sync-staging.yaml index 19ad631d4f..14a62fd35a 100644 --- a/.github/workflows/sync-staging.yaml +++ b/.github/workflows/sync-staging.yaml @@ -8,7 +8,7 @@ jobs: git-mirror: runs-on: ubuntu-latest steps: - - uses: zent-contrib/git-branch-sync-action@v1 + - uses: zent-contrib/git-branch-sync-action@v1.0.0 env: SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} with: From 7b8b97e0289895a670ad8ca1bb8a687b7bf674a1 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Mon, 25 Mar 2024 12:40:16 -0500 Subject: [PATCH 18/49] Update sync-staging.yaml --- .github/workflows/sync-staging.yaml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/sync-staging.yaml b/.github/workflows/sync-staging.yaml index 14a62fd35a..1fa6932330 100644 --- a/.github/workflows/sync-staging.yaml +++ b/.github/workflows/sync-staging.yaml @@ -8,9 +8,12 @@ jobs: git-mirror: runs-on: ubuntu-latest steps: - - uses: zent-contrib/git-branch-sync-action@v1.0.0 - env: - SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + - uses: actions/checkout@v4 + - uses: net-engine/github-repository-sync-action@v1 with: - source-branch: amd-staging - destination-repo: "git@github.com:ROCm/rocprofiler-register.git" + # The SSH private key for SSH connection to the target repository. + # We strongly recommend saving this value as a GitHub Secret and using deploy + # keys within the target repository + ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} + # The SSH-based URL to the target repository + target_repo_url: git@github.com:ROCm/rocprofiler-register.git From 52dfa074ae947a14ee23c124b14ec584925b287b Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Mon, 25 Mar 2024 12:44:54 -0500 Subject: [PATCH 19/49] Update sync-staging.yaml --- .github/workflows/sync-staging.yaml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sync-staging.yaml b/.github/workflows/sync-staging.yaml index 1fa6932330..2896b9db49 100644 --- a/.github/workflows/sync-staging.yaml +++ b/.github/workflows/sync-staging.yaml @@ -8,12 +8,11 @@ jobs: git-mirror: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: net-engine/github-repository-sync-action@v1 + - name: git-sync + uses: wei/git-sync@v3 with: - # The SSH private key for SSH connection to the target repository. - # We strongly recommend saving this value as a GitHub Secret and using deploy - # keys within the target repository + source_repo: "git@github.com:ROCm/rocprofiler-register-internal.git" + source_branch: "amd-staging" + destination_repo: "git@github.com:ROCm/rocprofiler-register.git" + destination_branch: "amd-staging" ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} - # The SSH-based URL to the target repository - target_repo_url: git@github.com:ROCm/rocprofiler-register.git From 1e59ce36209396ca935474ad952b8eef0e941734 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Mon, 25 Mar 2024 12:46:08 -0500 Subject: [PATCH 20/49] Update sync-mainline.yaml --- .github/workflows/sync-mainline.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/sync-mainline.yaml b/.github/workflows/sync-mainline.yaml index 6c807142ed..b4a7297d85 100644 --- a/.github/workflows/sync-mainline.yaml +++ b/.github/workflows/sync-mainline.yaml @@ -8,9 +8,11 @@ jobs: git-mirror: runs-on: ubuntu-latest steps: - - uses: zent-contrib/git-branch-sync-action@v1 - env: - SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + - name: git-sync + uses: wei/git-sync@v3 with: - source-branch: amd-mainline - destination-repo: "git@github.com:ROCm/rocprofiler-register.git" + source_repo: "git@github.com:ROCm/rocprofiler-register-internal.git" + source_branch: "amd-mainline" + destination_repo: "git@github.com:ROCm/rocprofiler-register.git" + destination_branch: "amd-mainline" + ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} From eb005aac74973ed6c179d28aa219150d14844a65 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Mon, 25 Mar 2024 12:51:38 -0500 Subject: [PATCH 21/49] Update .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9e03c05ae7..5e2bdf9c4c 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,5 @@ /compile_commands.json # Github Workflows -/.github/workflows/continuous-integration.yml +.github/workflows/continuous-integration.yml +.github/workflows/*.yaml From f18651d9f123ea55590969a9af57b835bfc5d3d9 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Tue, 23 Apr 2024 08:22:31 -0500 Subject: [PATCH 22/49] Update rocprofiler_register_config_packaging.cmake --- cmake/rocprofiler_register_config_packaging.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index 99014567ae..d47f53a4ec 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -75,6 +75,8 @@ else() set(CPACK_RPM_PACKAGE_REQUIRES "") endif() +set(CPACK_RPM_PACKAGE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") + foreach(COMPONENT_GROUP ${ROCPROFILER_REGISTER_COMPONENT_GROUPS}) set(_SEP "${COMPONENT_SEP_${COMPONENT_GROUP}}") set(_DEP "${COMPONENT_DEP_${COMPONENT_GROUP}}") From 64a0e626e4ecd61e6bfeb7054e0d6a2c814c1e46 Mon Sep 17 00:00:00 2001 From: Ammar ELWazir Date: Tue, 23 Apr 2024 09:00:44 -0500 Subject: [PATCH 23/49] Adding License to core package --- cmake/rocprofiler_register_config_packaging.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index d47f53a4ec..41d4e50fbe 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -77,6 +77,12 @@ endif() set(CPACK_RPM_PACKAGE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +# Install license file +install( + FILES ${CPACK_RESOURCE_FILE_LICENSE} + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT core) + foreach(COMPONENT_GROUP ${ROCPROFILER_REGISTER_COMPONENT_GROUPS}) set(_SEP "${COMPONENT_SEP_${COMPONENT_GROUP}}") set(_DEP "${COMPONENT_DEP_${COMPONENT_GROUP}}") From 2b777139d38fad61f316190c952453d53f4d9d83 Mon Sep 17 00:00:00 2001 From: Joseph Macaranas <145489236+amd-jmacaran@users.noreply.github.com> Date: Thu, 25 Apr 2024 14:41:30 -0400 Subject: [PATCH 24/49] Add support for external CI builds using Azure Pipelines (#62) * Add support for external CI builds using Azure Pipelines * Change token name to match IT-created token --- .azuredevops/rocm-ci.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .azuredevops/rocm-ci.yml diff --git a/.azuredevops/rocm-ci.yml b/.azuredevops/rocm-ci.yml new file mode 100644 index 0000000000..8f6f2242c8 --- /dev/null +++ b/.azuredevops/rocm-ci.yml @@ -0,0 +1,39 @@ +resources: + repositories: + - repository: pipelines_repo + type: github + endpoint: ROCm + name: ROCm/ROCm + +variables: +- group: common +- template: /.azuredevops/variables-global.yml@pipelines_repo + +trigger: + batch: true + branches: + include: + - amd-mainline + - amd-staging + paths: + exclude: + - .github + - LICENSE + - README.md + - VERSION + +pr: + autoCancel: true + branches: + include: + - amd-staging + paths: + exclude: + - .github + - LICENSE + - README.md + - VERSION + drafts: false + +jobs: + - template: ${{ variables.CI_COMPONENT_PATH }}/rocprofiler-register.yml@pipelines_repo From dd231244ee523bdbd391f6bac8d33bf185d2c6f6 Mon Sep 17 00:00:00 2001 From: raramakr <91213141+raramakr@users.noreply.github.com> Date: Thu, 25 Apr 2024 13:55:14 -0700 Subject: [PATCH 25/49] SWDEV-448381 - CPACK dependency list should be comma separated (#61) * SWDEV-448381 - CPACK dependency list should be comma separated * Remove redundant code and update the dependency list in first place * Update cmake/rocprofiler_register_config_packaging.cmake --------- Co-authored-by: Jonathan R. Madsen --- cmake/rocprofiler_register_config_packaging.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index 41d4e50fbe..ea7b8fb4d4 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -97,6 +97,8 @@ foreach(COMPONENT_GROUP ${ROCPROFILER_REGISTER_COMPONENT_GROUPS}) if(ROCM_DEP_ROCMCORE OR ROCPROFILER_REGISTER_DEP_ROCMCORE) list(INSERT _DEP 0 "rocm-core") endif() + # Dependency list should be separated by comma + string(REPLACE ";" ", " _DEP "${_DEP}") string(TOUPPER "${COMPONENT_GROUP}" UCOMPONENT) set(CPACK_DEBIAN_${UCOMPONENT}_PACKAGE_NAME "${PROJECT_NAME}${_SEP}${_NAME}") From 11a4668306e91d347d4343d421f7d524b9d3b0df Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Thu, 25 Apr 2024 16:04:09 -0500 Subject: [PATCH 26/49] Fix CPACK_RPM_PACKAGE_LICENSE (#63) - move install command for license to rocprofiler_register_config_install.cmake - CPACK_RPM_PACKAGE_LICENSE should be set to license type (i.e. "MIT"), not the path to the license file --- cmake/rocprofiler_register_config_install.cmake | 5 +++++ cmake/rocprofiler_register_config_packaging.cmake | 9 +-------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/cmake/rocprofiler_register_config_install.cmake b/cmake/rocprofiler_register_config_install.cmake index d7493d9b47..1a5e69156a 100644 --- a/cmake/rocprofiler_register_config_install.cmake +++ b/cmake/rocprofiler_register_config_install.cmake @@ -3,6 +3,11 @@ include_guard(GLOBAL) include(CMakePackageConfigHelpers) +install( + FILES ${PROJECT_SOURCE_DIR}/LICENSE + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT core) + install( EXPORT rocprofiler-register-library-targets FILE rocprofiler-register-library-targets.cmake diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index ea7b8fb4d4..5e98f3e53a 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -75,14 +75,6 @@ else() set(CPACK_RPM_PACKAGE_REQUIRES "") endif() -set(CPACK_RPM_PACKAGE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") - -# Install license file -install( - FILES ${CPACK_RESOURCE_FILE_LICENSE} - DESTINATION ${CMAKE_INSTALL_DOCDIR} - COMPONENT core) - foreach(COMPONENT_GROUP ${ROCPROFILER_REGISTER_COMPONENT_GROUPS}) set(_SEP "${COMPONENT_SEP_${COMPONENT_GROUP}}") set(_DEP "${COMPONENT_DEP_${COMPONENT_GROUP}}") @@ -188,6 +180,7 @@ if(CPACK_RPM_PACKAGE_RELEASE) set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) endif() set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") +set(CPACK_RPM_PACKAGE_LICENSE "MIT") # -------------------------------------------------------------------------------------- # # From b71f9cabe6055386d2a2c6d669d4574bbd0e2ad0 Mon Sep 17 00:00:00 2001 From: Mythreya Date: Wed, 11 Sep 2024 15:57:51 -0700 Subject: [PATCH 27/49] Add rccl API support (#66) * [Draft]: Add rccl API support * Partial tests Need to add tests to the cmake file --- .../rocprofiler_register.cpp | 6 + tests/CMakeLists.txt | 1 + tests/common/fwd.h | 8 + tests/common/fwd.hpp | 10 ++ tests/rccl/CMakeLists.txt | 33 ++++ tests/rccl/rccl.cpp | 149 ++++++++++++++++++ tests/rccl/rccl.hpp | 46 ++++++ tests/rocprofiler/rocprofiler.cpp | 14 ++ 8 files changed, 267 insertions(+) create mode 100644 tests/rccl/CMakeLists.txt create mode 100644 tests/rccl/rccl.cpp create mode 100644 tests/rccl/rccl.hpp diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 7c09d2f09b..3cabb87ab0 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -105,6 +105,7 @@ enum rocp_reg_supported_library // NOLINT(performance-enum-size) ROCP_REG_HIP, ROCP_REG_ROCTX, ROCP_REG_HIP_COMPILER, + ROCP_REG_RCCL, ROCP_REG_LAST, }; @@ -159,6 +160,11 @@ ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_HIP_COMPILER, "rocprofiler_register_import_hip_compiler", "libamdhip64.so.[6-9]($|\\.[0-9\\.]+)") +ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_RCCL, + "rccl", + "rocprofiler_register_import_rccl", + "librccl.so.[6-9]($|\\.[0-9\\.]+)") + ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_SUCCESS, "Success") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_NO_TOOLS, "rocprofiler-register found no tools") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_DEADLOCK, "rocprofiler-register deadlocked") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1349669016..36aca52be9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -71,6 +71,7 @@ endif() add_subdirectory(hsa-runtime) add_subdirectory(amdhip) add_subdirectory(roctx) +add_subdirectory(rccl) add_subdirectory(rocprofiler) # diff --git a/tests/common/fwd.h b/tests/common/fwd.h index 571c66c0d4..5d6dcb21c1 100644 --- a/tests/common/fwd.h +++ b/tests/common/fwd.h @@ -12,6 +12,7 @@ extern "C" { # pragma weak hsa_init # pragma weak roctxRangePush # pragma weak roctxRangePop +# pragma weak ncclGetVersion #endif extern void @@ -26,6 +27,13 @@ roctxRangePush(const char*); extern void roctxRangePop(const char*); +enum ncclResult_t +{ +}; + +extern ncclResult_t +ncclGetVersion(int* version); + #ifdef __cplusplus } #endif diff --git a/tests/common/fwd.hpp b/tests/common/fwd.hpp index 6438a2a77b..c9956568e2 100644 --- a/tests/common/fwd.hpp +++ b/tests/common/fwd.hpp @@ -18,6 +18,7 @@ namespace { decltype(hip_init)* hip_init_fn = nullptr; decltype(hsa_init)* hsa_init_fn = nullptr; +decltype(ncclGetVersion)* ncclGetVersion_fn = nullptr; decltype(roctxRangePush)* roctxRangePush_fn = nullptr; decltype(roctxRangePush)* roctxRangePop_fn = nullptr; @@ -27,6 +28,7 @@ enum rocp_reg_test_modes : uint8_t ROCP_REG_TEST_HIP = (1 << 0), ROCP_REG_TEST_HSA = (1 << 1), ROCP_REG_TEST_ROCTX = (1 << 2), + ROCP_REG_TEST_RCCL = (1 << 3), }; template @@ -73,6 +75,7 @@ resolve_symbols(int _open_mode = RTLD_LOCAL | RTLD_LAZY) void* amdhip_handle = nullptr; void* hsart_handle = nullptr; void* roctx_handle = nullptr; + void* rccl_handle = nullptr; if constexpr((Idx & ROCP_REG_TEST_HIP) == ROCP_REG_TEST_HIP) { @@ -97,5 +100,12 @@ resolve_symbols(int _open_mode = RTLD_LOCAL | RTLD_LAZY) _resolve_dlsym(roctxRangePush_fn, roctx_handle, "roctxRangePush"); _resolve_dlsym(roctxRangePop_fn, roctx_handle, "roctxRangePop"); } + + if constexpr((Idx & ROCP_REG_TEST_RCCL) == ROCP_REG_TEST_RCCL) + { + ncclGetVersion_fn = ncclGetVersion; + if(!ncclGetVersion_fn) _resolve_dlopen(rccl_handle, "librccl.so"); + _resolve_dlsym(ncclGetVersion_fn, rccl_handle, "ncclGetVersion"); + } } } // namespace diff --git a/tests/rccl/CMakeLists.txt b/tests/rccl/CMakeLists.txt new file mode 100644 index 0000000000..b9764ac0b3 --- /dev/null +++ b/tests/rccl/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# +# + +if(NOT TARGET rocprofiler-register::rocprofiler-register) + # find_package(rocprofiler-register REQUIRED) +endif() + +add_library(rccl SHARED) +add_library(rccl::rccl ALIAS rccl) +target_sources(rccl PRIVATE rccl.cpp rccl.hpp) +target_include_directories(rccl PUBLIC $) +target_link_libraries(rccl PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + rccl + PROPERTIES OUTPUT_NAME rccl + SOVERSION 1 + VERSION 1.0) +rocp_register_strip_target(rccl) + +add_library(rccl-invalid SHARED) +add_library(rccl::rccl-invalid ALIAS rccl-invalid) +target_sources(rccl-invalid PRIVATE rccl.cpp rccl.hpp) +target_include_directories(rccl-invalid + PUBLIC $) +target_link_libraries(rccl-invalid PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + rccl-invalid + PROPERTIES OUTPUT_NAME rccl + SOVERSION 1 + VERSION 1.0 + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid) +rocp_register_strip_target(rccl-invalid) diff --git a/tests/rccl/rccl.cpp b/tests/rccl/rccl.cpp new file mode 100644 index 0000000000..3607888267 --- /dev/null +++ b/tests/rccl/rccl.cpp @@ -0,0 +1,149 @@ +#include "rccl.hpp" + +#include + +#include +#include +#include +#include + +#define ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_2(RCCL_API_TRACE_VERSION_MAJOR, \ + RCCL_API_TRACE_VERSION_PATCH) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(rccl, ROCP_REG_VERSION) + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace rccl +{ +namespace +{ +auto& +get_rccl_api_table_impl() +{ + static auto _table = std::atomic{ nullptr }; + return _table; +} + +void +register_profiler_impl() +{ + static auto _const_api_table = rcclApiFuncTable{}; + initialize_rccl_api_table(&_const_api_table); + + // set this before any recursive opportunity arises + get_rccl_api_table_impl().exchange(&_const_api_table); + + // create a copy of the api table for modification by registration + static auto _profiler_api_table = rcclApiFuncTable{}; + copy_rccl_api_table(&_profiler_api_table, &_const_api_table); + + void* _profiler_api_table_v = static_cast(&_profiler_api_table); + + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto success = + rocprofiler_register_library_api_table("rccl", + &ROCPROFILER_REGISTER_IMPORT_FUNC(rccl), + ROCP_REG_VERSION, + &_profiler_api_table_v, + 1, + &lib_id); + + if(success == 0) + { + printf("[%s] rccl identifier %lu\n", ROCP_REG_FILE_NAME, lib_id.handle); + auto* _api_table = &_const_api_table; + if(!get_rccl_api_table_impl().compare_exchange_strong(_api_table, + &_profiler_api_table)) + { + // with the current impl, if we ever get here, someone is calling one the + // functions in this anonymous namespace that shouldn't + std::cerr + << "register_profiler_impl expected the API table to be the internal " + "implementation and yet it is not. something went wrong.\n"; + abort(); + } + } + else if(success != ROCP_REG_NO_TOOLS) + { + std::cerr << "rccl library failed to register with rocprofiler-register: " + << rocprofiler_register_error_string(success) << "\n"; + exit(EXIT_FAILURE); + } +} + +void +register_profiler() +{ + // this registration scheme is designed to minimize overhead once + // registered (only pay cost of checking atomic boolean) + // once the profiler is registered. If the library has not + // been registered and two or more threads try to register concurrently + // the first thread to acquire the lock below, will block the + // threads until registration is complete. However, + // if the same thread performing the registration re-enters this function + // i.e. this library's API is called during registration, this function + // will prevent a deadlock by not attempting to re-enter the + // the call-once and not releasing any waiting threads by flipping + // the _is_registered field to true. + static auto _is_registered = std::atomic{ false }; + + if(!_is_registered.load(std::memory_order_acquire)) + { + using mutex_t = std::recursive_mutex; + using auto_lock_t = std::unique_lock; + static auto _once = std::once_flag{}; + static auto _mutex = mutex_t{}; + + // defer the lock so we can check for recursion + auto _lk = auto_lock_t{ _mutex, std::defer_lock }; + + // this will be true if the same thread currently executing the call_once invokes + // the library's API while registering the profiler (e.g. tool which wants to + // instrument rccl API invokes a rccl function while registering with the + // profiler) we allow this thread to proceed and access the "const" API table but + // return so it does not flip _is_registered to true, which would result + // in any subsequent threads not waiting until the library is fully registered, + // resulting in missed callbacks for the tools + if(_lk.owns_lock()) return; + + // ensures any subsequent threads wait until the first thread + // finishes registration + _lk.lock(); + // call_once to ensure that we only register once + std::call_once(_once, register_profiler_impl); + // the first thread has completed registration and all + // threads waiting on lock will be released and this + // block will not be entered again + _is_registered.exchange(true, std::memory_order_release); + } +} +} // namespace + +rcclApiFuncTable* +get_rccl_api_table() +{ + register_profiler(); + return get_rccl_api_table_impl().load(std::memory_order_relaxed); +} + +void +rccl_init() +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} +} // namespace rccl + +extern "C" { +void +rccl_init(void) +{ + rccl::get_rccl_api_table()->ncclGetVersion_fn({}); +} +} diff --git a/tests/rccl/rccl.hpp b/tests/rccl/rccl.hpp new file mode 100644 index 0000000000..d220f1da13 --- /dev/null +++ b/tests/rccl/rccl.hpp @@ -0,0 +1,46 @@ +#pragma once + +#define RCCL_API_TRACE_VERSION_MAJOR 0 +#define RCCL_API_TRACE_VERSION_PATCH 0 + +#include +#include + +extern "C" { +// fake rccl function +typedef int ncclResult_t; + +enum ncclDataType_t +{ +}; + +ncclResult_t +ncclGetVersion(int* version) __attribute__((visibility("default"))); +} + +namespace rccl +{ +struct rcclApiFuncTable +{ + uint64_t size = 0; + decltype(::ncclGetVersion)* ncclGetVersion_fn = nullptr; +}; + +ncclResult_t +ncclGetVersion(int* version); + +// populates rccl api table with function pointers +inline void +initialize_rccl_api_table(rcclApiFuncTable* dst) +{ + dst->size = sizeof(rcclApiFuncTable); + dst->ncclGetVersion_fn = &::rccl::ncclGetVersion; +} + +// copies the api table from src to dst +inline void +copy_rccl_api_table(rcclApiFuncTable* dst, const rcclApiFuncTable* src) +{ + *dst = *src; +} +} // namespace rccl diff --git a/tests/rocprofiler/rocprofiler.cpp b/tests/rocprofiler/rocprofiler.cpp index 519cb7ebee..087c7ead30 100644 --- a/tests/rocprofiler/rocprofiler.cpp +++ b/tests/rocprofiler/rocprofiler.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -29,6 +30,13 @@ hsa_init() printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); } +ncclResult_t +ncclGetVersion(int*) +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); + return {}; +} + void roctx_range_push(const char* name) { @@ -78,6 +86,7 @@ rocprofiler_set_api_table(const char* name, using hip_table_t = hip::HipApiTable; using hsa_table_t = hsa::HsaApiTable; using roctx_table_t = roctx::ROCTxApiTable; + using rccl_table_t = rccl::rcclApiFuncTable; auto* _wrap_v = std::getenv("ROCP_REG_TEST_WRAP"); bool _wrap = (_wrap_v != nullptr && std::stoi(_wrap_v) != 0); @@ -107,6 +116,11 @@ rocprofiler_set_api_table(const char* name, _table->roctxRangePush_fn = &rocprofiler::roctx_range_push; _table->roctxRangePop_fn = &rocprofiler::roctx_range_pop; } + else if(std::string_view{ name } == "rccl") + { + rccl_table_t* _table = static_cast(tables[0]); + _table->ncclGetVersion_fn = &rocprofiler::ncclGetVersion; + } } return 0; From f809f21740a49a4e1c5c8add11ed8f156f3b0615 Mon Sep 17 00:00:00 2001 From: "Choudhary, Rahul" Date: Tue, 7 Jan 2025 11:09:50 -0800 Subject: [PATCH 28/49] Create rocm_ci_caller.yml --- .github/workflows/rocm_ci_caller.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/rocm_ci_caller.yml diff --git a/.github/workflows/rocm_ci_caller.yml b/.github/workflows/rocm_ci_caller.yml new file mode 100644 index 0000000000..5d543b74e9 --- /dev/null +++ b/.github/workflows/rocm_ci_caller.yml @@ -0,0 +1,22 @@ +name: ROCm CI Caller + +on: + pull_request: + branches: [amd-staging] + types: [opened, reopened, synchronize] + push: + branches: [amd-mainline] + workflow_dispatch: + +jobs: + call-workflow: + uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/rocm_ci.yml@mainline + secrets: inherit + with: + input_sha: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + input_pr_num: ${{ github.event_name == 'pull_request' && github.event.pull_request.number || 0 }} + input_pr_url: ${{ github.event_name == 'pull_request' && github.event.pull_request.html_url || '' }} + input_pr_title: ${{ github.event_name == 'pull_request' && github.event.pull_request.title || '' }} + repository_name: ${{ github.repository }} + base_ref: ${{ github.event_name == 'pull_request' && github.base_ref || github.ref }} + trigger_event_type: ${{ github.event_name }} From 11c9259043fa70cd5a4933773b1ebbb0302bf8e5 Mon Sep 17 00:00:00 2001 From: "Elwazir, Ammar" Date: Wed, 8 Jan 2025 09:50:04 -0600 Subject: [PATCH 29/49] Update Github Workflows (#2) * Update sync-mainline.yaml * Update sync-staging.yaml * Update formatting.yml --- .github/workflows/formatting.yml | 30 ---------------------------- .github/workflows/sync-mainline.yaml | 7 +++---- .github/workflows/sync-staging.yaml | 7 +++---- 3 files changed, 6 insertions(+), 38 deletions(-) diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 7fca0a0777..c8030700b3 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -46,16 +46,6 @@ jobs: exit 1 fi - - name: Create pull request - if: failure() - uses: peter-evans/create-pull-request@v5 - with: - commit-message: "cmake formatting (cmake-format)" - branch: ${{ steps.extract_branch.outputs.branch }}-cmake-format - delete-branch: true - title: "Format cmake code (via cmake-format) on ${{ steps.extract_branch.outputs.branch }}" - base: ${{ steps.extract_branch.outputs.branch }} - source: runs-on: ubuntu-22.04 @@ -88,16 +78,6 @@ jobs: exit 1 fi - - name: Create pull request - if: failure() - uses: peter-evans/create-pull-request@v5 - with: - commit-message: "source formatting (clang-format v11)" - branch: ${{ steps.extract_branch.outputs.branch }}-clang-format - delete-branch: true - title: "Format source code (via clang-format v11) on ${{ steps.extract_branch.outputs.branch }}" - base: ${{ steps.extract_branch.outputs.branch }} - python: runs-on: ubuntu-22.04 strategy: @@ -134,13 +114,3 @@ jobs: git diff exit 1 fi - - - name: Create pull request - if: failure() - uses: peter-evans/create-pull-request@v5 - with: - commit-message: "python formatting (black)" - branch: ${{ steps.extract_branch.outputs.branch }}-python-format - delete-branch: true - title: "Format python code (via black) on ${{ steps.extract_branch.outputs.branch }}" - base: ${{ steps.extract_branch.outputs.branch }} diff --git a/.github/workflows/sync-mainline.yaml b/.github/workflows/sync-mainline.yaml index b4a7297d85..33c4315c02 100644 --- a/.github/workflows/sync-mainline.yaml +++ b/.github/workflows/sync-mainline.yaml @@ -9,10 +9,9 @@ jobs: runs-on: ubuntu-latest steps: - name: git-sync - uses: wei/git-sync@v3 + uses: AMD-ROCm-Internal/rocprofiler-github-actions@git-sync-v3 with: - source_repo: "git@github.com:ROCm/rocprofiler-register-internal.git" + source_repo: "https://${{ secrets.TOKEN }}@github.com/AMD-ROCm-Internal/rocprofiler-register-internal.git" source_branch: "amd-mainline" - destination_repo: "git@github.com:ROCm/rocprofiler-register.git" + destination_repo: "https://${{ secrets.EXT_TOKEN }}@github.com/ROCm/rocprofiler-register.git" destination_branch: "amd-mainline" - ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} diff --git a/.github/workflows/sync-staging.yaml b/.github/workflows/sync-staging.yaml index 2896b9db49..2e3ce6dd1b 100644 --- a/.github/workflows/sync-staging.yaml +++ b/.github/workflows/sync-staging.yaml @@ -9,10 +9,9 @@ jobs: runs-on: ubuntu-latest steps: - name: git-sync - uses: wei/git-sync@v3 + uses: AMD-ROCm-Internal/rocprofiler-github-actions@git-sync-v3 with: - source_repo: "git@github.com:ROCm/rocprofiler-register-internal.git" + source_repo: "https://${{ secrets.TOKEN }}@github.com/AMD-ROCm-Internal/rocprofiler-register-internal.git" source_branch: "amd-staging" - destination_repo: "git@github.com:ROCm/rocprofiler-register.git" + destination_repo: "https://${{ secrets.EXT_TOKEN }}@github.com/ROCm/rocprofiler-register.git" destination_branch: "amd-staging" - ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} From 3bd980bff8edcb10b49f7c5b7948c1910cdd844e Mon Sep 17 00:00:00 2001 From: "Mallya, Ameya Keshava" Date: Wed, 15 Jan 2025 11:15:00 -0800 Subject: [PATCH 30/49] Added KWS check --- .github/workflows/kws-caller.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/kws-caller.yml diff --git a/.github/workflows/kws-caller.yml b/.github/workflows/kws-caller.yml new file mode 100644 index 0000000000..f2a515e5b0 --- /dev/null +++ b/.github/workflows/kws-caller.yml @@ -0,0 +1,29 @@ +###################################################################################### +# Name : Rocm Validation Suite +# Developed by : kiran.thumma@amd.com, gajeambi@amd.com +# Maintained by : kiran.thumma@amd.com, gajendrad.ambi@amd.com +# Version : 0.5 +# Description : This workflow will eventually call the central rocm reusable workflow. +# So developers should not edit/Modify this file +# Donot add it into .*ignore file# +# Docs : +###################################################################################### +name: Rocm Validation Suite KWS +on: + push: + branches: [amd-staging] + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: + +jobs: + kws: + # runs only for PR events. Add 3 environment variables in repo's settings + # - PROJECT_NAME : your project's name in keywordsearch.amd.com + # - KEYWORD_SCAN_USER : your username in keywordsearch.amd.com to access the above project + # - KEYWORD_SCAN_PASSWORD : your password in keywordsearch.amd.com to access the above project + if: ${{ github.event_name == 'pull_request' }} + uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/kws.yml@mainline + secrets: inherit + with: + pr_number: ${{github.event.pull_request.number}} From 164eda523197ad33b6b912dd1e8e6e34f61ede7e Mon Sep 17 00:00:00 2001 From: "Mallya, Ameya Keshava" Date: Fri, 17 Jan 2025 08:25:42 -0800 Subject: [PATCH 31/49] Fixed Workflow for updated KWS structure --- .github/workflows/kws-caller.yml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/kws-caller.yml b/.github/workflows/kws-caller.yml index f2a515e5b0..ffcbff7b1e 100644 --- a/.github/workflows/kws-caller.yml +++ b/.github/workflows/kws-caller.yml @@ -1,13 +1,3 @@ -###################################################################################### -# Name : Rocm Validation Suite -# Developed by : kiran.thumma@amd.com, gajeambi@amd.com -# Maintained by : kiran.thumma@amd.com, gajendrad.ambi@amd.com -# Version : 0.5 -# Description : This workflow will eventually call the central rocm reusable workflow. -# So developers should not edit/Modify this file -# Donot add it into .*ignore file# -# Docs : -###################################################################################### name: Rocm Validation Suite KWS on: push: @@ -15,15 +5,11 @@ on: pull_request: types: [opened, synchronize, reopened] workflow_dispatch: - jobs: kws: - # runs only for PR events. Add 3 environment variables in repo's settings - # - PROJECT_NAME : your project's name in keywordsearch.amd.com - # - KEYWORD_SCAN_USER : your username in keywordsearch.amd.com to access the above project - # - KEYWORD_SCAN_PASSWORD : your password in keywordsearch.amd.com to access the above project if: ${{ github.event_name == 'pull_request' }} uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/kws.yml@mainline secrets: inherit with: pr_number: ${{github.event.pull_request.number}} + base_branch: ${{github.base_ref}} From de3a874b1a9b2d5ba26f9728333f00e24695aa6d Mon Sep 17 00:00:00 2001 From: "Trowbridge, Ian" Date: Tue, 21 Jan 2025 21:00:43 -0600 Subject: [PATCH 32/49] Add rocDecode API support (#4) * Add rocDecode API support * Update CI * CI update: Sanitizers run on ubuntu 22.04 --------- Co-authored-by: Jonathan R. Madsen --- .github/workflows/continuous-integration.yml | 12 +- scripts/run-ci.py | 2 +- .../rocprofiler_register.cpp | 6 + tests/CMakeLists.txt | 1 + tests/common/fwd.h | 17 ++ tests/common/fwd.hpp | 38 +++-- tests/rocdecode/CMakeLists.txt | 34 ++++ tests/rocdecode/rocdecode.cpp | 149 ++++++++++++++++++ tests/rocdecode/rocdecode.hpp | 55 +++++++ tests/rocprofiler/rocprofiler.cpp | 22 ++- 10 files changed, 313 insertions(+), 23 deletions(-) create mode 100644 tests/rocdecode/CMakeLists.txt create mode 100644 tests/rocdecode/rocdecode.cpp create mode 100644 tests/rocdecode/rocdecode.hpp diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index f2a14a77c6..7c1220f87c 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: runner: ['ubuntu-latest'] - compiler: ['clang-13', 'clang-14', 'clang-15', 'gcc-11', 'gcc-12'] + compiler: ['clang-14', 'clang-15', 'gcc-11', 'gcc-12'] ci-args: [''] ci-tag: [''] include: @@ -40,15 +40,19 @@ jobs: compiler: 'clang-10' ci-args: '' ci-tag: '' - - runner: 'ubuntu-latest' + - runner: 'ubuntu-22.04' + compiler: 'clang-13' + ci-args: '' + ci-tag: '' + - runner: 'ubuntu-22.04' compiler: 'gcc-12' ci-args: '--memcheck ThreadSanitizer' ci-tag: '-thread-sanitizer' - - runner: 'ubuntu-latest' + - runner: 'ubuntu-22.04' compiler: 'gcc-12' ci-args: '--memcheck AddressSanitizer' ci-tag: '-address-sanitizer' - - runner: 'ubuntu-latest' + - runner: 'ubuntu-22.04' compiler: 'gcc-12' ci-args: '--memcheck LeakSanitizer' ci-tag: '-leak-sanitizer' diff --git a/scripts/run-ci.py b/scripts/run-ci.py index c4d9b4eb13..7e2309fcf4 100755 --- a/scripts/run-ci.py +++ b/scripts/run-ci.py @@ -13,7 +13,7 @@ import multiprocessing # this constant is used to define CTEST_PROJECT_NAME # and default value for CTEST_SUBMIT_URL _PROJECT_NAME = "rocprofiler-register" -_BASE_URL = "10.194.116.31/cdash" +_BASE_URL = "cdash.rocprofiler.amd.com" def which(cmd, require): diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 3cabb87ab0..619deba9b8 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -106,6 +106,7 @@ enum rocp_reg_supported_library // NOLINT(performance-enum-size) ROCP_REG_ROCTX, ROCP_REG_HIP_COMPILER, ROCP_REG_RCCL, + ROCP_REG_ROCDECODE, ROCP_REG_LAST, }; @@ -165,6 +166,11 @@ ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_RCCL, "rocprofiler_register_import_rccl", "librccl.so.[6-9]($|\\.[0-9\\.]+)") +ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_ROCDECODE, + "rocdecode", + "rocprofiler_register_import_rocdecode", + "librocdecode.so.[0-9]($|\\.[0-9\\.]+)") + ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_SUCCESS, "Success") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_NO_TOOLS, "rocprofiler-register found no tools") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_DEADLOCK, "rocprofiler-register deadlocked") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 36aca52be9..3482ca7005 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -72,6 +72,7 @@ add_subdirectory(hsa-runtime) add_subdirectory(amdhip) add_subdirectory(roctx) add_subdirectory(rccl) +add_subdirectory(rocdecode) add_subdirectory(rocprofiler) # diff --git a/tests/common/fwd.h b/tests/common/fwd.h index 5d6dcb21c1..057b3e1b70 100644 --- a/tests/common/fwd.h +++ b/tests/common/fwd.h @@ -13,6 +13,7 @@ extern "C" { # pragma weak roctxRangePush # pragma weak roctxRangePop # pragma weak ncclGetVersion +# pragma weak rocDecCreateDecoder #endif extern void @@ -34,6 +35,22 @@ enum ncclResult_t extern ncclResult_t ncclGetVersion(int* version); +enum rocDecStatus +{ +}; + +enum rocDecDecoderHandle +{ +}; + +enum RocDecoderCreateInfo +{ +}; + +extern rocDecStatus +rocDecCreateDecoder(rocDecDecoderHandle* decoder_handle, + RocDecoderCreateInfo* decoder_create_info); + #ifdef __cplusplus } #endif diff --git a/tests/common/fwd.hpp b/tests/common/fwd.hpp index c9956568e2..91e30c35ef 100644 --- a/tests/common/fwd.hpp +++ b/tests/common/fwd.hpp @@ -16,19 +16,21 @@ namespace { -decltype(hip_init)* hip_init_fn = nullptr; -decltype(hsa_init)* hsa_init_fn = nullptr; -decltype(ncclGetVersion)* ncclGetVersion_fn = nullptr; -decltype(roctxRangePush)* roctxRangePush_fn = nullptr; -decltype(roctxRangePush)* roctxRangePop_fn = nullptr; +decltype(hip_init)* hip_init_fn = nullptr; +decltype(hsa_init)* hsa_init_fn = nullptr; +decltype(ncclGetVersion)* ncclGetVersion_fn = nullptr; +decltype(roctxRangePush)* roctxRangePush_fn = nullptr; +decltype(roctxRangePush)* roctxRangePop_fn = nullptr; +decltype(rocDecCreateDecoder)* rocDecCreateDecoder_fn = nullptr; enum rocp_reg_test_modes : uint8_t { - ROCP_REG_TEST_NONE = 0x0, - ROCP_REG_TEST_HIP = (1 << 0), - ROCP_REG_TEST_HSA = (1 << 1), - ROCP_REG_TEST_ROCTX = (1 << 2), - ROCP_REG_TEST_RCCL = (1 << 3), + ROCP_REG_TEST_NONE = 0x0, + ROCP_REG_TEST_HIP = (1 << 0), + ROCP_REG_TEST_HSA = (1 << 1), + ROCP_REG_TEST_ROCTX = (1 << 2), + ROCP_REG_TEST_RCCL = (1 << 3), + ROCP_REG_TEST_ROCDECODE = (1 << 4), }; template @@ -72,10 +74,11 @@ resolve_symbols(int _open_mode = RTLD_LOCAL | RTLD_LAZY) } }; - void* amdhip_handle = nullptr; - void* hsart_handle = nullptr; - void* roctx_handle = nullptr; - void* rccl_handle = nullptr; + void* amdhip_handle = nullptr; + void* hsart_handle = nullptr; + void* roctx_handle = nullptr; + void* rccl_handle = nullptr; + void* rocdecode_handle = nullptr; if constexpr((Idx & ROCP_REG_TEST_HIP) == ROCP_REG_TEST_HIP) { @@ -107,5 +110,12 @@ resolve_symbols(int _open_mode = RTLD_LOCAL | RTLD_LAZY) if(!ncclGetVersion_fn) _resolve_dlopen(rccl_handle, "librccl.so"); _resolve_dlsym(ncclGetVersion_fn, rccl_handle, "ncclGetVersion"); } + + if constexpr((Idx & ROCP_REG_TEST_ROCDECODE) == ROCP_REG_TEST_ROCDECODE) + { + rocDecCreateDecoder_fn = rocDecCreateDecoder; + if(!rocDecCreateDecoder_fn) _resolve_dlopen(rocdecode_handle, "librocdecode.so"); + _resolve_dlsym(rocDecCreateDecoder_fn, rocdecode_handle, "rocDecCreateDecoder"); + } } } // namespace diff --git a/tests/rocdecode/CMakeLists.txt b/tests/rocdecode/CMakeLists.txt new file mode 100644 index 0000000000..5f5e4112c7 --- /dev/null +++ b/tests/rocdecode/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# +# + +if(NOT TARGET rocprofiler-register::rocprofiler-register) + # find_package(rocprofiler-register REQUIRED) +endif() + +add_library(rocdecode SHARED) +add_library(rocdecode::rocdecode ALIAS rocdecode) +target_sources(rocdecode PRIVATE rocdecode.cpp rocdecode.hpp) +target_include_directories(rocdecode PUBLIC $) +target_link_libraries(rocdecode PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + rocdecode + PROPERTIES OUTPUT_NAME rocdecode + SOVERSION 1 + VERSION 1.0) +rocp_register_strip_target(rocdecode) + +add_library(rocdecode-invalid SHARED) +add_library(rocdecode::rocdecode-invalid ALIAS rocdecode-invalid) +target_sources(rocdecode-invalid PRIVATE rocdecode.cpp rocdecode.hpp) +target_include_directories(rocdecode-invalid + PUBLIC $) +target_link_libraries(rocdecode-invalid + PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + rocdecode-invalid + PROPERTIES OUTPUT_NAME rocdecode + SOVERSION 1 + VERSION 1.0 + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid) +rocp_register_strip_target(rocdecode-invalid) diff --git a/tests/rocdecode/rocdecode.cpp b/tests/rocdecode/rocdecode.cpp new file mode 100644 index 0000000000..3a99fe04ff --- /dev/null +++ b/tests/rocdecode/rocdecode.cpp @@ -0,0 +1,149 @@ +#include "rocdecode.hpp" + +#include + +#include +#include +#include +#include + +#define ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_2(ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION, \ + ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(rocdecode, ROCP_REG_VERSION) + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace rocdecode +{ +namespace +{ +auto& +get_rocdecode_api_table_impl() +{ + static auto _table = std::atomic{ nullptr }; + return _table; +} + +void +register_profiler_impl() +{ + static auto _const_api_table = rocdecodeApiFuncTable{}; + initialize_rocdecode_api_table(&_const_api_table); + + // set this before any recursive opportunity arises + get_rocdecode_api_table_impl().exchange(&_const_api_table); + + // create a copy of the api table for modification by registration + static auto _profiler_api_table = rocdecodeApiFuncTable{}; + copy_rocdecode_api_table(&_profiler_api_table, &_const_api_table); + + void* _profiler_api_table_v = static_cast(&_profiler_api_table); + + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto success = rocprofiler_register_library_api_table( + "rocdecode", + &ROCPROFILER_REGISTER_IMPORT_FUNC(rocdecode), + ROCP_REG_VERSION, + &_profiler_api_table_v, + 1, + &lib_id); + + if(success == 0) + { + printf("[%s] rocdecode identifier %lu\n", ROCP_REG_FILE_NAME, lib_id.handle); + auto* _api_table = &_const_api_table; + if(!get_rocdecode_api_table_impl().compare_exchange_strong(_api_table, + &_profiler_api_table)) + { + // with the current impl, if we ever get here, someone is calling one the + // functions in this anonymous namespace that shouldn't + std::cerr + << "register_profiler_impl expected the API table to be the internal " + "implementation and yet it is not. something went wrong.\n"; + abort(); + } + } + else if(success != ROCP_REG_NO_TOOLS) + { + std::cerr << "rocdecode library failed to register with rocprofiler-register: " + << rocprofiler_register_error_string(success) << "\n"; + exit(EXIT_FAILURE); + } +} + +void +register_profiler() +{ + // this registration scheme is designed to minimize overhead once + // registered (only pay cost of checking atomic boolean) + // once the profiler is registered. If the library has not + // been registered and two or more threads try to register concurrently + // the first thread to acquire the lock below, will block the + // threads until registration is complete. However, + // if the same thread performing the registration re-enters this function + // i.e. this library's API is called during registration, this function + // will prevent a deadlock by not attempting to re-enter the + // the call-once and not releasing any waiting threads by flipping + // the _is_registered field to true. + static auto _is_registered = std::atomic{ false }; + + if(!_is_registered.load(std::memory_order_acquire)) + { + using mutex_t = std::recursive_mutex; + using auto_lock_t = std::unique_lock; + static auto _once = std::once_flag{}; + static auto _mutex = mutex_t{}; + + // defer the lock so we can check for recursion + auto _lk = auto_lock_t{ _mutex, std::defer_lock }; + + // this will be true if the same thread currently executing the call_once invokes + // the library's API while registering the profiler (e.g. tool which wants to + // instrument rocdecode API invokes a rocdecode function while registering with + // the profiler) we allow this thread to proceed and access the "const" API table + // but return so it does not flip _is_registered to true, which would result in + // any subsequent threads not waiting until the library is fully registered, + // resulting in missed callbacks for the tools + if(_lk.owns_lock()) return; + + // ensures any subsequent threads wait until the first thread + // finishes registration + _lk.lock(); + // call_once to ensure that we only register once + std::call_once(_once, register_profiler_impl); + // the first thread has completed registration and all + // threads waiting on lock will be released and this + // block will not be entered again + _is_registered.exchange(true, std::memory_order_release); + } +} +} // namespace + +rocdecodeApiFuncTable* +get_rocdecode_api_table() +{ + register_profiler(); + return get_rocdecode_api_table_impl().load(std::memory_order_relaxed); +} + +void +rocdecode_init() +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} +} // namespace rocdecode + +extern "C" { +void +rocdecode_init(void) +{ + rocdecode::get_rocdecode_api_table()->rocDecCreateDecoder_fn({}, {}); +} +} diff --git a/tests/rocdecode/rocdecode.hpp b/tests/rocdecode/rocdecode.hpp new file mode 100644 index 0000000000..e1706e939d --- /dev/null +++ b/tests/rocdecode/rocdecode.hpp @@ -0,0 +1,55 @@ +#pragma once + +#define ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION 0 +#define ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION 1 + +#include +#include + +extern "C" { +// fake rccl function +enum rocDecStatus +{ +}; + +enum rocDecDecoderHandle +{ +}; + +enum RocDecoderCreateInfo +{ +}; + +rocDecStatus +rocDecCreateDecoder(rocDecDecoderHandle* decoder_handle, + RocDecoderCreateInfo* decoder_create_info) + __attribute__((visibility("default"))); +} + +namespace rocdecode +{ +struct rocdecodeApiFuncTable +{ + uint64_t size = 0; + decltype(::rocDecCreateDecoder)* rocDecCreateDecoder_fn = nullptr; +}; + +rocDecStatus +rocDecCreateDecoder(rocDecDecoderHandle* decoder_handle, + RocDecoderCreateInfo* decoder_create_info); + +// populates rocdecode api table with function pointers +inline void +initialize_rocdecode_api_table(rocdecodeApiFuncTable* dst) +{ + dst->size = sizeof(rocdecodeApiFuncTable); + dst->rocDecCreateDecoder_fn = &::rocdecode::rocDecCreateDecoder; +} + +// copies the api table from src to dst +inline void +copy_rocdecode_api_table(rocdecodeApiFuncTable* dst, const rocdecodeApiFuncTable* src) +{ + *dst = *src; +} +} // namespace rocdecode diff --git a/tests/rocprofiler/rocprofiler.cpp b/tests/rocprofiler/rocprofiler.cpp index 087c7ead30..63418badd6 100644 --- a/tests/rocprofiler/rocprofiler.cpp +++ b/tests/rocprofiler/rocprofiler.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,13 @@ ncclGetVersion(int*) return {}; } +rocDecStatus +rocDecCreateDecoder(rocDecDecoderHandle*, RocDecoderCreateInfo*) +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); + return {}; +} + void roctx_range_push(const char* name) { @@ -83,10 +91,11 @@ rocprofiler_set_api_table(const char* name, " did not contain rocprofiler_configure symbol" }; } - using hip_table_t = hip::HipApiTable; - using hsa_table_t = hsa::HsaApiTable; - using roctx_table_t = roctx::ROCTxApiTable; - using rccl_table_t = rccl::rcclApiFuncTable; + using hip_table_t = hip::HipApiTable; + using hsa_table_t = hsa::HsaApiTable; + using roctx_table_t = roctx::ROCTxApiTable; + using rccl_table_t = rccl::rcclApiFuncTable; + using rocdecode_table_t = rocdecode::rocdecodeApiFuncTable; auto* _wrap_v = std::getenv("ROCP_REG_TEST_WRAP"); bool _wrap = (_wrap_v != nullptr && std::stoi(_wrap_v) != 0); @@ -121,6 +130,11 @@ rocprofiler_set_api_table(const char* name, rccl_table_t* _table = static_cast(tables[0]); _table->ncclGetVersion_fn = &rocprofiler::ncclGetVersion; } + else if(std::string_view{ name } == "rocdecode") + { + rocdecode_table_t* _table = static_cast(tables[0]); + _table->rocDecCreateDecoder_fn = &rocprofiler::rocDecCreateDecoder; + } } return 0; From 366716af06806caa6f8a834e20bceabc0f752403 Mon Sep 17 00:00:00 2001 From: "Trowbridge, Ian" Date: Mon, 27 Jan 2025 11:50:12 -0600 Subject: [PATCH 33/49] Support for rocJPEG Tracing (#5) * Add initial support for rocJPEG API Trace * Added tests for rocjpeg * Formatting --- .../rocprofiler_register.cpp | 6 + tests/CMakeLists.txt | 1 + tests/common/fwd.h | 12 ++ tests/common/fwd.hpp | 10 ++ tests/rocjpeg/CMakeLists.txt | 33 ++++ tests/rocjpeg/rocjpeg.cpp | 149 ++++++++++++++++++ tests/rocjpeg/rocjpeg.hpp | 49 ++++++ tests/rocprofiler/rocprofiler.cpp | 14 ++ 8 files changed, 274 insertions(+) create mode 100644 tests/rocjpeg/CMakeLists.txt create mode 100644 tests/rocjpeg/rocjpeg.cpp create mode 100644 tests/rocjpeg/rocjpeg.hpp diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 619deba9b8..0905eddd66 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -107,6 +107,7 @@ enum rocp_reg_supported_library // NOLINT(performance-enum-size) ROCP_REG_HIP_COMPILER, ROCP_REG_RCCL, ROCP_REG_ROCDECODE, + ROCP_REG_ROCJPEG, ROCP_REG_LAST, }; @@ -171,6 +172,11 @@ ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_ROCDECODE, "rocprofiler_register_import_rocdecode", "librocdecode.so.[0-9]($|\\.[0-9\\.]+)") +ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_ROCJPEG, + "rocjpeg", + "rocprofiler_register_import_rocjpeg", + "librocjpeg.so.[0-9]($|\\.[0-9\\.]+)") + ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_SUCCESS, "Success") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_NO_TOOLS, "rocprofiler-register found no tools") ROCP_REG_DEFINE_ERROR_MESSAGE(ROCP_REG_DEADLOCK, "rocprofiler-register deadlocked") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3482ca7005..d0da1bcc22 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -73,6 +73,7 @@ add_subdirectory(amdhip) add_subdirectory(roctx) add_subdirectory(rccl) add_subdirectory(rocdecode) +add_subdirectory(rocjpeg) add_subdirectory(rocprofiler) # diff --git a/tests/common/fwd.h b/tests/common/fwd.h index 057b3e1b70..bd7be6030a 100644 --- a/tests/common/fwd.h +++ b/tests/common/fwd.h @@ -14,6 +14,7 @@ extern "C" { # pragma weak roctxRangePop # pragma weak ncclGetVersion # pragma weak rocDecCreateDecoder +# pragma weak rocJpegStreamCreate #endif extern void @@ -51,6 +52,17 @@ extern rocDecStatus rocDecCreateDecoder(rocDecDecoderHandle* decoder_handle, RocDecoderCreateInfo* decoder_create_info); +enum RocJpegStatus +{ +}; + +enum RocJpegStreamHandle +{ +}; + +extern RocJpegStatus +rocJpegStreamCreate(RocJpegStreamHandle* jpeg_stream_handle); + #ifdef __cplusplus } #endif diff --git a/tests/common/fwd.hpp b/tests/common/fwd.hpp index 91e30c35ef..d740658dea 100644 --- a/tests/common/fwd.hpp +++ b/tests/common/fwd.hpp @@ -22,6 +22,7 @@ decltype(ncclGetVersion)* ncclGetVersion_fn = nullptr; decltype(roctxRangePush)* roctxRangePush_fn = nullptr; decltype(roctxRangePush)* roctxRangePop_fn = nullptr; decltype(rocDecCreateDecoder)* rocDecCreateDecoder_fn = nullptr; +decltype(rocJpegStreamCreate)* rocJpegStreamCreate_fn = nullptr; enum rocp_reg_test_modes : uint8_t { @@ -31,6 +32,7 @@ enum rocp_reg_test_modes : uint8_t ROCP_REG_TEST_ROCTX = (1 << 2), ROCP_REG_TEST_RCCL = (1 << 3), ROCP_REG_TEST_ROCDECODE = (1 << 4), + ROCP_REG_TEST_ROCJPEG = (1 << 5), }; template @@ -79,6 +81,7 @@ resolve_symbols(int _open_mode = RTLD_LOCAL | RTLD_LAZY) void* roctx_handle = nullptr; void* rccl_handle = nullptr; void* rocdecode_handle = nullptr; + void* rocjpeg_handle = nullptr; if constexpr((Idx & ROCP_REG_TEST_HIP) == ROCP_REG_TEST_HIP) { @@ -117,5 +120,12 @@ resolve_symbols(int _open_mode = RTLD_LOCAL | RTLD_LAZY) if(!rocDecCreateDecoder_fn) _resolve_dlopen(rocdecode_handle, "librocdecode.so"); _resolve_dlsym(rocDecCreateDecoder_fn, rocdecode_handle, "rocDecCreateDecoder"); } + + if constexpr((Idx & ROCP_REG_TEST_ROCJPEG) == ROCP_REG_TEST_ROCJPEG) + { + rocJpegStreamCreate_fn = rocJpegStreamCreate; + if(!rocJpegStreamCreate_fn) _resolve_dlopen(rocjpeg_handle, "librocjpeg.so"); + _resolve_dlsym(rocJpegStreamCreate_fn, rocjpeg_handle, "rocJpegStreamCreate"); + } } } // namespace diff --git a/tests/rocjpeg/CMakeLists.txt b/tests/rocjpeg/CMakeLists.txt new file mode 100644 index 0000000000..ffa306ab3b --- /dev/null +++ b/tests/rocjpeg/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# +# + +if(NOT TARGET rocprofiler-register::rocprofiler-register) + # find_package(rocprofiler-register REQUIRED) +endif() + +add_library(rocjpeg SHARED) +add_library(rocjpeg::rocjpeg ALIAS rocjpeg) +target_sources(rocjpeg PRIVATE rocjpeg.cpp rocjpeg.hpp) +target_include_directories(rocjpeg PUBLIC $) +target_link_libraries(rocjpeg PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + rocjpeg + PROPERTIES OUTPUT_NAME rocjpeg + SOVERSION 1 + VERSION 1.0) +rocp_register_strip_target(rocjpeg) + +add_library(rocjpeg-invalid SHARED) +add_library(rocjpeg::rocjpeg-invalid ALIAS rocjpeg-invalid) +target_sources(rocjpeg-invalid PRIVATE rocjpeg.cpp rocjpeg.hpp) +target_include_directories(rocjpeg-invalid + PUBLIC $) +target_link_libraries(rocjpeg-invalid PRIVATE rocprofiler-register::rocprofiler-register) +set_target_properties( + rocjpeg-invalid + PROPERTIES OUTPUT_NAME rocjpeg + SOVERSION 1 + VERSION 1.0 + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/invalid) +rocp_register_strip_target(rocjpeg-invalid) diff --git a/tests/rocjpeg/rocjpeg.cpp b/tests/rocjpeg/rocjpeg.cpp new file mode 100644 index 0000000000..e77944439a --- /dev/null +++ b/tests/rocjpeg/rocjpeg.cpp @@ -0,0 +1,149 @@ +#include "rocjpeg.hpp" + +#include + +#include +#include +#include +#include + +#define ROCP_REG_VERSION \ + ROCPROFILER_REGISTER_COMPUTE_VERSION_2(ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION, \ + ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION) + +ROCPROFILER_REGISTER_DEFINE_IMPORT(rocjpeg, ROCP_REG_VERSION) + +#ifndef ROCP_REG_FILE_NAME +# define ROCP_REG_FILE_NAME \ + ::std::string{ __FILE__ } \ + .substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \ + .c_str() +#endif + +namespace rocjpeg +{ +namespace +{ +auto& +get_rocjpeg_api_table_impl() +{ + static auto _table = std::atomic{ nullptr }; + return _table; +} + +void +register_profiler_impl() +{ + static auto _const_api_table = rocjpegApiFuncTable{}; + initialize_rocjpeg_api_table(&_const_api_table); + + // set this before any recursive opportunity arises + get_rocjpeg_api_table_impl().exchange(&_const_api_table); + + // create a copy of the api table for modification by registration + static auto _profiler_api_table = rocjpegApiFuncTable{}; + copy_rocjpeg_api_table(&_profiler_api_table, &_const_api_table); + + void* _profiler_api_table_v = static_cast(&_profiler_api_table); + + auto lib_id = rocprofiler_register_library_indentifier_t{}; + auto success = + rocprofiler_register_library_api_table("rocjpeg", + &ROCPROFILER_REGISTER_IMPORT_FUNC(rocjpeg), + ROCP_REG_VERSION, + &_profiler_api_table_v, + 1, + &lib_id); + + if(success == 0) + { + printf("[%s] rocjpeg identifier %lu\n", ROCP_REG_FILE_NAME, lib_id.handle); + auto* _api_table = &_const_api_table; + if(!get_rocjpeg_api_table_impl().compare_exchange_strong(_api_table, + &_profiler_api_table)) + { + // with the current impl, if we ever get here, someone is calling one the + // functions in this anonymous namespace that shouldn't + std::cerr + << "register_profiler_impl expected the API table to be the internal " + "implementation and yet it is not. something went wrong.\n"; + abort(); + } + } + else if(success != ROCP_REG_NO_TOOLS) + { + std::cerr << "rocjpeg library failed to register with rocprofiler-register: " + << rocprofiler_register_error_string(success) << "\n"; + exit(EXIT_FAILURE); + } +} + +void +register_profiler() +{ + // this registration scheme is designed to minimize overhead once + // registered (only pay cost of checking atomic boolean) + // once the profiler is registered. If the library has not + // been registered and two or more threads try to register concurrently + // the first thread to acquire the lock below, will block the + // threads until registration is complete. However, + // if the same thread performing the registration re-enters this function + // i.e. this library's API is called during registration, this function + // will prevent a deadlock by not attempting to re-enter the + // the call-once and not releasing any waiting threads by flipping + // the _is_registered field to true. + static auto _is_registered = std::atomic{ false }; + + if(!_is_registered.load(std::memory_order_acquire)) + { + using mutex_t = std::recursive_mutex; + using auto_lock_t = std::unique_lock; + static auto _once = std::once_flag{}; + static auto _mutex = mutex_t{}; + + // defer the lock so we can check for recursion + auto _lk = auto_lock_t{ _mutex, std::defer_lock }; + + // this will be true if the same thread currently executing the call_once invokes + // the library's API while registering the profiler (e.g. tool which wants to + // instrument rocjpeg API invokes a rocjpeg function while registering with + // the profiler) we allow this thread to proceed and access the "const" API table + // but return so it does not flip _is_registered to true, which would result in + // any subsequent threads not waiting until the library is fully registered, + // resulting in missed callbacks for the tools + if(_lk.owns_lock()) return; + + // ensures any subsequent threads wait until the first thread + // finishes registration + _lk.lock(); + // call_once to ensure that we only register once + std::call_once(_once, register_profiler_impl); + // the first thread has completed registration and all + // threads waiting on lock will be released and this + // block will not be entered again + _is_registered.exchange(true, std::memory_order_release); + } +} +} // namespace + +rocjpegApiFuncTable* +get_rocjpeg_api_table() +{ + register_profiler(); + return get_rocjpeg_api_table_impl().load(std::memory_order_relaxed); +} + +void +rocjpeg_init() +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); +} +} // namespace rocjpeg + +extern "C" { +void +rocjpeg_init(void) +{ + rocjpeg::get_rocjpeg_api_table()->rocJpegStreamCreate_fn({}); +} +} diff --git a/tests/rocjpeg/rocjpeg.hpp b/tests/rocjpeg/rocjpeg.hpp new file mode 100644 index 0000000000..dbd053b2ef --- /dev/null +++ b/tests/rocjpeg/rocjpeg.hpp @@ -0,0 +1,49 @@ +#pragma once + +#define ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION 0 +#define ROCDECODE_RUNTIME_API_TABLE_STEP_VERSION 1 + +#include +#include + +extern "C" { +// fake rccl function +enum RocJpegStatus +{ +}; + +enum RocJpegStreamHandle +{ +}; + +RocJpegStatus +rocJpegStreamCreate(RocJpegStreamHandle* jpeg_stream_handle) + __attribute__((visibility("default"))); +} + +namespace rocjpeg +{ +struct rocjpegApiFuncTable +{ + uint64_t size = 0; + decltype(::rocJpegStreamCreate)* rocJpegStreamCreate_fn = nullptr; +}; + +RocJpegStatus +rocJpegStreamCreate(RocJpegStreamHandle* jpeg_stream_handle); + +// populates rocjpeg api table with function pointers +inline void +initialize_rocjpeg_api_table(rocjpegApiFuncTable* dst) +{ + dst->size = sizeof(rocjpegApiFuncTable); + dst->rocJpegStreamCreate_fn = &::rocjpeg::rocJpegStreamCreate; +} + +// copies the api table from src to dst +inline void +copy_rocjpeg_api_table(rocjpegApiFuncTable* dst, const rocjpegApiFuncTable* src) +{ + *dst = *src; +} +} // namespace rocjpeg diff --git a/tests/rocprofiler/rocprofiler.cpp b/tests/rocprofiler/rocprofiler.cpp index 63418badd6..eac61cadff 100644 --- a/tests/rocprofiler/rocprofiler.cpp +++ b/tests/rocprofiler/rocprofiler.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,13 @@ rocDecCreateDecoder(rocDecDecoderHandle*, RocDecoderCreateInfo*) return {}; } +RocJpegStatus +rocJpegStreamCreate(RocJpegStreamHandle* jpeg_stream_handle) +{ + printf("[%s] %s\n", ROCP_REG_FILE_NAME, __FUNCTION__); + return {}; +} + void roctx_range_push(const char* name) { @@ -96,6 +104,7 @@ rocprofiler_set_api_table(const char* name, using roctx_table_t = roctx::ROCTxApiTable; using rccl_table_t = rccl::rcclApiFuncTable; using rocdecode_table_t = rocdecode::rocdecodeApiFuncTable; + using rocjpeg_table_t = rocjpeg::rocjpegApiFuncTable; auto* _wrap_v = std::getenv("ROCP_REG_TEST_WRAP"); bool _wrap = (_wrap_v != nullptr && std::stoi(_wrap_v) != 0); @@ -135,6 +144,11 @@ rocprofiler_set_api_table(const char* name, rocdecode_table_t* _table = static_cast(tables[0]); _table->rocDecCreateDecoder_fn = &rocprofiler::rocDecCreateDecoder; } + else if(std::string_view{ name } == "rocjpeg") + { + rocjpeg_table_t* _table = static_cast(tables[0]); + _table->rocJpegStreamCreate_fn = &rocprofiler::rocJpegStreamCreate; + } } return 0; From 7d691bc53332d189d664581276c6f989faac7653 Mon Sep 17 00:00:00 2001 From: "Mallya, Ameya Keshava" Date: Tue, 28 Jan 2025 20:17:23 -0800 Subject: [PATCH 34/49] Added !verify trigger --- .github/workflows/rocm_ci_caller.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rocm_ci_caller.yml b/.github/workflows/rocm_ci_caller.yml index 5d543b74e9..77c6349e4f 100644 --- a/.github/workflows/rocm_ci_caller.yml +++ b/.github/workflows/rocm_ci_caller.yml @@ -6,10 +6,13 @@ on: types: [opened, reopened, synchronize] push: branches: [amd-mainline] - workflow_dispatch: + workflow_dispatch: + issue_comment: + types: [created] jobs: call-workflow: + if: ${{ github.event_name != 'issue_comment' || github.event.comment.body == '!verify' }} uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/rocm_ci.yml@mainline secrets: inherit with: From b6c5f9133a1978f207fa52d2221e0282f20ab94f Mon Sep 17 00:00:00 2001 From: "Mallya, Ameya Keshava" Date: Fri, 14 Mar 2025 14:08:06 -0700 Subject: [PATCH 35/49] Added release trigger for further releases --- .github/workflows/rocm_ci_caller.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rocm_ci_caller.yml b/.github/workflows/rocm_ci_caller.yml index 77c6349e4f..5373d66535 100644 --- a/.github/workflows/rocm_ci_caller.yml +++ b/.github/workflows/rocm_ci_caller.yml @@ -2,7 +2,7 @@ name: ROCm CI Caller on: pull_request: - branches: [amd-staging] + branches: [amd-staging, release/rocm-rel-*] types: [opened, reopened, synchronize] push: branches: [amd-mainline] From cb1b43025168f351589d85672fac07e0fca8c929 Mon Sep 17 00:00:00 2001 From: "Madsen, Jonathan" Date: Fri, 21 Mar 2025 01:23:45 -0500 Subject: [PATCH 36/49] Logging updates (#7) * General logging updates * ROCm 6.1.x fatal defect: unconditional abort if tool found but rocprofiler-sdk missing - Adding rocprofiler-sdk support breaks backwards compatibility in ROCm 6.1.x because `rocprofiler_configure` symbol triggers looking for rocprofiler-sdk library (which was not released until ROCm 6.2) - Bump version to 0.5.0 * revert to using fatal error * Include header updates * Fix CodeQL suggestions * CMake and CI updates - minimum cmake version is 3.22.0 - added requirements.txt - improved rocprofiler_register_{formatting,linting}.cmake * Disable deprecated declarations warnings * Use "overwrite" instead of "override" - override is a keyword in C++ * Disable REQUIRED for formatting and linting when BUILD_DEVELOPER=ON --------- Co-authored-by: Jonathan R. Madsen --- .github/workflows/continuous-integration.yml | 3 +- CMakeLists.txt | 2 +- README.md | 29 ++- VERSION | 2 +- .../rocprofiler_register_build_settings.cmake | 3 +- cmake/rocprofiler_register_formatting.cmake | 49 +++- cmake/rocprofiler_register_linting.cmake | 35 ++- cmake/rocprofiler_register_options.cmake | 4 +- external/CMakeLists.txt | 2 +- external/glog | 2 +- requirements.txt | 5 + .../details/CMakeLists.txt | 4 +- .../details/environment.hpp | 32 ++- .../rocprofiler-register/details/logging.cpp | 229 ++++++++++++++++++ .../rocprofiler-register/details/logging.hpp | 37 +++ .../rocprofiler_register.cpp | 44 +++- tests/CMakeLists.txt | 5 + tests/bin/CMakeLists.txt | 108 +++++++++ tests/bin/simple-hip.cpp | 174 +++++++++++++ 19 files changed, 720 insertions(+), 49 deletions(-) create mode 100644 requirements.txt create mode 100644 source/lib/rocprofiler-register/details/logging.cpp create mode 100644 source/lib/rocprofiler-register/details/logging.hpp create mode 100644 tests/bin/CMakeLists.txt create mode 100644 tests/bin/simple-hip.cpp diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 7c1220f87c..b437726573 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -81,7 +81,8 @@ jobs: sudo update-alternatives --install /usr/bin/cc cc /usr/bin/${CC} 100 && sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/${CXX} 100 && python3 -m pip install --upgrade pip && - python3 -m pip install 'cmake==3.21.4' + python3 -m pip install 'cmake==3.22.0' && + python3 -m pip install -r requirements.txt - name: Setup GCov timeout-minutes: 25 diff --git a/CMakeLists.txt b/CMakeLists.txt index 30d13080e7..2fdf5c4ec4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16 FATAL_ERROR) +cmake_minimum_required(VERSION 3.22.0 FATAL_ERROR) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) diff --git a/README.md b/README.md index 5ce882f48e..227b3e4475 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,27 @@ ## Overview -The rocprofiler-register library is a helper library that coordinates the modification of the intercept API table(s) of the HSA/HIP/ROCTx -runtime libraries by the ROCprofiler (v2) library. The purpose of this library is to provide a consistent and automated mechanism +The rocprofiler-register library is a helper library that coordinates the modification of the intercept API table(s) of the HSA/HIP/ROCTx +runtime libraries by the ROCprofiler (v2) library. The purpose of this library is to provide a consistent and automated mechanism of enabling performance analysis in the ROCm runtimes which does not rely on environment variables or unique methods for each runtime -library. +library. When a runtime is initialized (either explicitly and lazily) and the intercept API table is constructed, it passes this API table to -rocprofiler-register. Rocprofiler-register scans the symbols in the address space and if it detects there is at least one visible symbol named -`rocprofiler_configure` (which is a function provided by tools), it passes the intercept API table to the rocprofiler library (dlopening +rocprofiler-register. Rocprofiler-register scans the symbols in the address space and if it detects there is at least one visible symbol named +`rocprofiler_configure` (which is a function provided by tools), it passes the intercept API table to the rocprofiler library (dlopening the rocprofiler library if it is not already loaded). The rocprofiler library then does an extensive scan for _all_ the instances of the `rocprofiler_configure` symbols and invokes each of them. The `rocprofiler_configure` function (again, provided by a tool) returns effectively tells rocprofiler which behaviors it wants to be notified about, features it wants to use (e.g. API tracing, kernel dispatch timing), -etc. +etc. + +## Environment Variables + +| Environment Variable | Description | Default Value | +|-----------------------------------|---------------------------------------------------------------------------|----------------| +| `ROCP_TOOL_LIBRARIES` | List of rocprofiler-sdk tool libraries (space, comma, or colon separated) | Empty (string) | +| `ROCPROFILER_REGISTER_ENABLED` | Set to 0/false/no to disable rocprofiler-register | true (bool) | +| `ROCPROFILER_REGISTER_SECURE` | Additional checks to ensure authenticity of runtime libraries | false (bool) | +| `ROCPROFILER_REGISTER_FORCE_LOAD` | Load rocprofiler-sdk library regardless of whether there is a tool or not | false (bool) | ## Contributing @@ -24,7 +33,7 @@ The default branch is `amd-mainline` but the only branch that should target that ### Creating a feature branch ```console -# fetch any updates +# fetch any updates git fetch origin # switch to staging branch @@ -44,18 +53,18 @@ branch as well. ### Pulling in updates to `amd-staging` to your feature branch -Linear histories are preferred so if another PR is merged into `amd-staging` while your PR is still open, please +Linear histories are preferred so if another PR is merged into `amd-staging` while your PR is still open, please select the "Update with rebase" option (i.e. try to avoid a merge commit). From the command line, the git command would be `git pull --rebase origin amd-staging`. ## Build and Installation rocprofiler-register has a standard CMake build and install process. E.g. the following configure -rocprofiler-register to build with optimizations and without debug info in a `build-rocp-reg` subdirectory, +rocprofiler-register to build with optimizations and without debug info in a `build-rocp-reg` subdirectory, build using 4 jobs, and install to `/opt/rocprofiler-register`: ```console -cmake -B build-rocp-reg . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/rocprofiler-register +cmake -B build-rocp-reg . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/rocprofiler-register cmake --build build-rocp-reg --target all --parallel 4 cmake --build build-rocp-reg --target install ``` diff --git a/VERSION b/VERSION index 1d0ba9ea18..8f0916f768 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.0 +0.5.0 diff --git a/cmake/rocprofiler_register_build_settings.cmake b/cmake/rocprofiler_register_build_settings.cmake index 00f8a3b402..e7ec51b29d 100644 --- a/cmake/rocprofiler_register_build_settings.cmake +++ b/cmake/rocprofiler_register_build_settings.cmake @@ -88,7 +88,8 @@ rocprofiler_register_target_compile_options( rocprofiler_register_target_compile_options( rocprofiler-register-developer-flags LANGUAGES C CXX - INTERFACE "-Werror" "-Wdouble-promotion" "-Wshadow" "-Wextra") + INTERFACE "-Werror" "-Wdouble-promotion" "-Wshadow" "-Wextra" + "-Wno-deprecated-declarations") if(ROCPROFILER_REGISTER_BUILD_DEVELOPER) target_link_libraries(rocprofiler-register-build-flags diff --git a/cmake/rocprofiler_register_formatting.cmake b/cmake/rocprofiler_register_formatting.cmake index 05e3c74a4a..9414a83ded 100644 --- a/cmake/rocprofiler_register_formatting.cmake +++ b/cmake/rocprofiler_register_formatting.cmake @@ -13,10 +13,41 @@ include_guard(DIRECTORY) -find_program(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE NAMES clang-format-11 - clang-format-mp-11) -find_program(ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE NAMES cmake-format) -find_program(ROCPROFILER_REGISTER_BLACK_FORMAT_EXE NAMES black) +if(NOT ROCPROFILER_REGISTER_CLANG_FORMAT_EXE AND EXISTS + $ENV{HOME}/.local/bin/clang-format) + execute_process( + COMMAND $ENV{HOME}/.local/bin/clang-format --version + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + OUTPUT_VARIABLE _CLANG_FMT_OUT + RESULT_VARIABLE _CLANG_FMT_RET + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(_CLANG_FMT_RET EQUAL 0) + if("${_CLANG_FMT_OUT}" MATCHES "version 11\\.([0-9]+)\\.([0-9]+)") + set(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE + "$ENV{HOME}/.local/bin/clang-format" + CACHE FILEPATH "clang-format exe") + endif() + endif() +endif() + +find_program( + ROCPROFILER_REGISTER_CLANG_FORMAT_EXE + NAMES clang-format-11 clang-format-mp-11 clang-format + PATHS $ENV{HOME}/.local + HINTS $ENV{HOME}/.local + PATH_SUFFIXES bin) +find_program( + ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE + NAMES cmake-format + PATHS $ENV{HOME}/.local + HINTS $ENV{HOME}/.local + PATH_SUFFIXES bin) +find_program( + ROCPROFILER_REGISTER_BLACK_FORMAT_EXE + NAMES black + PATHS $ENV{HOME}/.local + HINTS $ENV{HOME}/.local + PATH_SUFFIXES bin) add_custom_target(format-rocprofiler-register) if(NOT TARGET format) @@ -43,12 +74,14 @@ if(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE set(${_TYPE}) endforeach() file(GLOB_RECURSE header_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.h - ${PROJECT_SOURCE_DIR}/${_DIR}/*.hpp) + ${PROJECT_SOURCE_DIR}/${_DIR}/*.hpp ${PROJECT_SOURCE_DIR}/${_DIR}/*.h.in + ${PROJECT_SOURCE_DIR}/${_DIR}/*.hpp.in) file(GLOB_RECURSE source_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.c ${PROJECT_SOURCE_DIR}/${_DIR}/*.cpp) file(GLOB_RECURSE cmake_files ${PROJECT_SOURCE_DIR}/${_DIR}/*CMakeLists.txt ${PROJECT_SOURCE_DIR}/${_DIR}/*.cmake) - file(GLOB_RECURSE python_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.py) + file(GLOB_RECURSE python_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.py + ${PROJECT_SOURCE_DIR}/${_DIR}/*.py.in) foreach(_TYPE header_files source_files cmake_files python_files) list(APPEND rocp_${_TYPE} ${${_TYPE}}) endforeach() @@ -76,7 +109,7 @@ if(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE format-rocprofiler-register-python ${ROCPROFILER_REGISTER_BLACK_FORMAT_EXE} -q ${rocp_python_files} COMMENT - "[rocprofiler-register] Running Python formatter ${ROCPROFILER_REGISTER_BLACK_FORMAT_EXE}..." + "[rocprofiler-register] Running python formatter ${ROCPROFILER_REGISTER_BLACK_FORMAT_EXE}..." ) endif() @@ -85,7 +118,7 @@ if(ROCPROFILER_REGISTER_CLANG_FORMAT_EXE format-rocprofiler-register-cmake ${ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE} -i ${rocp_cmake_files} COMMENT - "[rocprofiler-register] Running CMake formatter ${ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE}..." + "[rocprofiler-register] Running cmake formatter ${ROCPROFILER_REGISTER_CMAKE_FORMAT_EXE}..." ) endif() diff --git a/cmake/rocprofiler_register_linting.cmake b/cmake/rocprofiler_register_linting.cmake index c8398bcd93..d5bfa11109 100644 --- a/cmake/rocprofiler_register_linting.cmake +++ b/cmake/rocprofiler_register_linting.cmake @@ -1,13 +1,30 @@ -include_guard(GLOBAL) - # ----------------------------------------------------------------------------------------# # # Clang Tidy # # ----------------------------------------------------------------------------------------# +include_guard(DIRECTORY) + +if(NOT ROCPROFILER_REGISTER_CLANG_TIDY_EXE AND EXISTS $ENV{HOME}/.local/bin/clang-tidy) + execute_process( + COMMAND $ENV{HOME}/.local/bin/clang-tidy --version + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + OUTPUT_VARIABLE _CLANG_TIDY_OUT + RESULT_VARIABLE _CLANG_TIDY_RET + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + + if(_CLANG_TIDY_RET EQUAL 0) + if("${_CLANG_TIDY_OUT}" MATCHES "version 1[5-9]\\.([0-9]+)\\.([0-9]+)") + set(ROCPROFILER_REGISTER_CLANG_TIDY_EXE + "$ENV{HOME}/.local/bin/clang-tidy" + CACHE FILEPATH "clang-tidy exe") + endif() + endif() +endif() + find_program( - ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND + ROCPROFILER_REGISTER_CLANG_TIDY_EXE NAMES clang-tidy-18 clang-tidy-17 clang-tidy-16 @@ -16,19 +33,25 @@ find_program( clang-tidy-13 clang-tidy-12 clang-tidy-11 - clang-tidy) + clang-tidy + PATHS $ENV{HOME}/.local + HINTS $ENV{HOME}/.local + PATH_SUFFIXES bin) macro(ROCPROFILER_REGISTER_ACTIVATE_CLANG_TIDY) if(ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) - if(NOT ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND) + if(NOT ROCPROFILER_REGISTER_CLANG_TIDY_EXE) message( FATAL_ERROR "ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY is ON but clang-tidy is not found!" ) endif() + rocprofiler_register_add_feature(ROCPROFILER_REGISTER_CLANG_TIDY_EXE + "path to clang-tidy executable") + set(CMAKE_CXX_CLANG_TIDY - ${ROCPROFILER_REGISTER_CLANG_TIDY_COMMAND} + ${ROCPROFILER_REGISTER_CLANG_TIDY_EXE} -header-filter=${PROJECT_SOURCE_DIR}/source/.* --warnings-as-errors=*,-misc-header-include-cycle) diff --git a/cmake/rocprofiler_register_options.cmake b/cmake/rocprofiler_register_options.cmake index 41e31bd088..790c0ca280 100644 --- a/cmake/rocprofiler_register_options.cmake +++ b/cmake/rocprofiler_register_options.cmake @@ -41,7 +41,9 @@ rocprofiler_register_add_option( ${ROCM_DEP_ROCMCORE}) # In the future, we will do this even with clang-tidy enabled -if(ROCPROFILER_REGISTER_BUILD_CI AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY) +if(ROCPROFILER_REGISTER_BUILD_CI + AND NOT ROCPROFILER_REGISTER_ENABLE_CLANG_TIDY + AND NOT ROCPROFILER_REGISTER_BUILD_DEVELOPER) message( STATUS "Forcing ROCPROFILER_REGISTER_BUILD_DEVELOPER=ON because ROCPROFILER_REGISTER_BUILD_CI=ON" diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 339f0a02b3..1bd36497a5 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -15,7 +15,7 @@ if(ROCPROFILER_REGISTER_BUILD_GLOG) # May want to use GFLAGS in the future set(WITH_GFLAGS OFF) set(WITH_GTEST OFF) - set(WITH_UNWIND OFF) + set(WITH_UNWIND "none") add_subdirectory(glog EXCLUDE_FROM_ALL) else() find_package(glog REQUIRED) diff --git a/external/glog b/external/glog index 3a0d4d22c5..7b134a5c82 160000 --- a/external/glog +++ b/external/glog @@ -1 +1 @@ -Subproject commit 3a0d4d22c5ae0b9a2216988411cfa6bf860cc372 +Subproject commit 7b134a5c82c0c0b5698bb6bf7a835b230c5638e4 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..58acea9e69 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +black +clang-format>=11.0.0,<12.0.0 +clang-tidy>=15.0.0,<19.0.0 +cmake>=3.22.0 +cmake-format diff --git a/source/lib/rocprofiler-register/details/CMakeLists.txt b/source/lib/rocprofiler-register/details/CMakeLists.txt index 71587dbd81..aa074aef5f 100644 --- a/source/lib/rocprofiler-register/details/CMakeLists.txt +++ b/source/lib/rocprofiler-register/details/CMakeLists.txt @@ -1,10 +1,10 @@ # # builds the rocprofiler-register library # -set(rocprofiler_register_details_sources dl.cpp utility.cpp) +set(rocprofiler_register_details_sources dl.cpp logging.cpp utility.cpp) set(rocprofiler_register_details_headers environment.hpp dl.hpp filesystem.hpp - utility.hpp) + logging.hpp utility.hpp) target_sources(rocprofiler-register PRIVATE ${rocprofiler_register_details_sources} ${rocprofiler_register_details_headers}) diff --git a/source/lib/rocprofiler-register/details/environment.hpp b/source/lib/rocprofiler-register/details/environment.hpp index 4250ed4de0..a0f10b5753 100644 --- a/source/lib/rocprofiler-register/details/environment.hpp +++ b/source/lib/rocprofiler-register/details/environment.hpp @@ -20,8 +20,8 @@ #pragma once -#include "fmt/core.h" -#include "glog/logging.h" +#include +#include #include #include @@ -106,6 +106,21 @@ get_env_impl(std::string_view env_id, bool _default) } return _default; } + +inline int +set_env_impl(std::string_view env_id, bool value, int overwrite) +{ + return ::setenv(env_id.data(), (value) ? "1" : "0", overwrite); +} + +template +int +set_env_impl(std::string_view env_id, Tp value, int overwrite) +{ + auto str_value = std::stringstream{}; + str_value << value; + return ::setenv(env_id.data(), str_value.str().c_str(), overwrite); +} } // namespace template @@ -124,18 +139,25 @@ get_env(std::string_view env_id, Tp&& _default) } } +template +inline auto +set_env(std::string_view env_id, Tp&& value, int overwrite = 0) +{ + return set_env_impl(env_id, std::forward(value), overwrite); +} + struct env_config { std::string env_name = {}; std::string env_value = {}; - int override = 0; + int overwrite = 0; auto operator()() const { if(env_name.empty()) return -1; LOG(INFO) << fmt::format( - "setenv({}, {}, {})", env_name.c_str(), env_value.c_str(), override); - return setenv(env_name.c_str(), env_value.c_str(), override); + "setenv({}, {}, {})", env_name.c_str(), env_value.c_str(), overwrite); + return setenv(env_name.c_str(), env_value.c_str(), overwrite); } }; } // namespace common diff --git a/source/lib/rocprofiler-register/details/logging.cpp b/source/lib/rocprofiler-register/details/logging.cpp new file mode 100644 index 0000000000..3f2005b7cb --- /dev/null +++ b/source/lib/rocprofiler-register/details/logging.cpp @@ -0,0 +1,229 @@ +// 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 "logging.hpp" +#include "environment.hpp" +#include "filesystem.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace rocprofiler_register +{ +namespace logging +{ +namespace +{ +struct logging_config +{ + bool logtostderr = true; + bool alsologtostderr = false; + bool logdir_gitignore = false; // add .gitignore to logdir + int32_t loglevel = google::WARNING; + std::string vlog_modules = {}; + std::string name = {}; + std::string logdir = {}; +}; + +struct log_level_info +{ + int32_t google_level = 0; + int32_t verbose_level = 0; +}; + +void +update_logging(const logging_config& cfg, bool setup_env = false, int env_override = 0) +{ + static auto _mtx = std::mutex{}; + auto _lk = std::unique_lock{ _mtx }; + + FLAGS_timestamp_in_logfile_name = false; + FLAGS_logtostderr = cfg.logtostderr; + FLAGS_minloglevel = cfg.loglevel; + FLAGS_stderrthreshold = cfg.loglevel; + FLAGS_alsologtostderr = cfg.alsologtostderr; + + // if(!cfg.logdir.empty()) FLAGS_log_dir = cfg.logdir.c_str(); + + if(!cfg.logdir.empty() && !fs::exists(cfg.logdir)) + { + fs::create_directories(cfg.logdir); + + if(cfg.logdir_gitignore) + { + auto ignore = fs::path{ cfg.logdir } / ".gitignore"; + if(!fs::exists(ignore)) + { + std::ofstream ofs{ ignore.string() }; + ofs << "/**" << std::flush; + } + } + } + + if(setup_env) + { + common::set_env("GLOG_minloglevel", cfg.loglevel, env_override); + common::set_env("GLOG_logtostderr", cfg.logtostderr ? 1 : 0, env_override); + common::set_env( + "GLOG_alsologtostderr", cfg.alsologtostderr ? 1 : 0, env_override); + common::set_env("GLOG_stderrthreshold", cfg.loglevel, env_override); + if(!cfg.logdir.empty()) + { + common::set_env("GOOGLE_LOG_DIR", cfg.logdir, env_override); + common::set_env("GLOG_log_dir", cfg.logdir, env_override); + } + if(!cfg.vlog_modules.empty()) + common::set_env("GLOG_vmodule", cfg.vlog_modules, env_override); + } +} + +#define ROCP_REG_LOG_LEVEL_TRACE 4 +#define ROCP_REG_LOG_LEVEL_INFO 3 +#define ROCP_REG_LOG_LEVEL_WARNING 2 +#define ROCP_REG_LOG_LEVEL_ERROR 1 +#define ROCP_REG_LOG_LEVEL_NONE 0 + +void +init_logging(std::string_view env_prefix, logging_config cfg = logging_config{}) +{ + static auto _once = std::once_flag{}; + std::call_once(_once, [env_prefix, &cfg]() { + auto get_argv0 = []() { + auto ifs = std::ifstream{ "/proc/self/cmdline" }; + auto sarg = std::string{}; + while(ifs && !ifs.eof()) + { + ifs >> sarg; + if(!sarg.empty()) break; + } + return sarg; + }; + + auto to_lower = [](std::string val) { + for(auto& itr : val) + itr = tolower(itr); + return val; + }; + + const auto env_opts = std::unordered_map{ + { "trace", { google::INFO, ROCP_REG_LOG_LEVEL_TRACE } }, + { "info", { google::INFO, ROCP_REG_LOG_LEVEL_INFO } }, + { "warning", { google::WARNING, ROCP_REG_LOG_LEVEL_WARNING } }, + { "error", { google::ERROR, ROCP_REG_LOG_LEVEL_ERROR } }, + { "fatal", { google::FATAL, ROCP_REG_LOG_LEVEL_NONE } } + }; + + auto supported = std::vector{}; + supported.reserve(env_opts.size()); + for(auto itr : env_opts) + supported.emplace_back(itr.first); + + if(cfg.name.empty()) cfg.name = to_lower(std::string{ env_prefix }); + + cfg.logdir = common::get_env(fmt::format("{}_LOG_DIR", env_prefix), cfg.logdir); + cfg.vlog_modules = + common::get_env(fmt::format("{}_vmodule", env_prefix), cfg.vlog_modules); + cfg.logtostderr = cfg.logdir.empty(); // log to stderr if no log dir set + // cfg.alsologtostderr = !cfg.logdir.empty(); // log to file if log dir set + + auto loglvl = + to_lower(common::get_env(fmt::format("{}_LOG_LEVEL", env_prefix), "")); + // default to warning + auto& loglvl_v = cfg.loglevel; + if(!loglvl.empty() && + loglvl.find_first_not_of("-0123456789") == std::string::npos) + { + auto val = std::stol(loglvl); + if(val < 0) + { + loglvl_v = google::FATAL; + } + else + { + // default to trace in case val > ROCP_REG_LOG_LEVEL_TRACE + auto itr = env_opts.at("trace"); + for(auto oitr : env_opts) + { + if(oitr.second.verbose_level == val) + { + itr = oitr.second; + break; + } + } + loglvl_v = itr.google_level; + } + } + else if(!loglvl.empty()) + { + if(env_opts.find(loglvl) == env_opts.end()) + throw std::runtime_error{ fmt::format( + "invalid specifier for {}_LOG_LEVEL: {}. Supported: {}", + env_prefix, + loglvl, + fmt::format("{}", + fmt::join(supported.begin(), supported.end(), ", "))) }; + else + { + loglvl_v = env_opts.at(loglvl).google_level; + } + } + + update_logging(cfg, !google::IsGoogleLoggingInitialized()); + + if(!google::IsGoogleLoggingInitialized()) + { + static auto argv0 = get_argv0(); + // Prevent glog from crashing if vmodule is empty + if(FLAGS_vmodule.empty()) FLAGS_vmodule = " "; + + google::InitGoogleLogging(argv0.c_str()); + + // Swap out memory to avoid leaking the string + if(!FLAGS_vmodule.empty()) std::string{}.swap(FLAGS_vmodule); + if(!FLAGS_log_dir.empty()) std::string{}.swap(FLAGS_log_dir); + } + + update_logging(cfg); + + LOG(INFO) << "logging initialized via " << fmt::format("{}_LOG_LEVEL", env_prefix) + << ". Log Level: " << loglvl; + }); +} +} // namespace + +void +initialize() +{ + init_logging("ROCPROFILER_REGISTER"); +} +} // namespace logging +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/details/logging.hpp b/source/lib/rocprofiler-register/details/logging.hpp new file mode 100644 index 0000000000..9f36d23b82 --- /dev/null +++ b/source/lib/rocprofiler-register/details/logging.hpp @@ -0,0 +1,37 @@ +// 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 +#include +#include +#include + +namespace rocprofiler_register +{ +namespace logging +{ +void +initialize(); +} // namespace logging +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index 0905eddd66..ff95239ac0 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -25,7 +25,10 @@ #include "details/dl.hpp" #include "details/environment.hpp" #include "details/filesystem.hpp" -#include "glog/logging.h" +#include "details/logging.hpp" + +#include +#include #include #include @@ -92,8 +95,6 @@ static_assert(sizeof(bitset_t) == sizeof(rocprofiler_register_library_indentifier_t::handle), "bitset should be same at uint64_t"); -int rocprofiler_register_verbose = common::get_env("ROCPROFILER_REGISTER_VERBOSE", 0); -constexpr int rocprofiler_register_info_level = 2; constexpr auto rocprofiler_lib_name = "librocprofiler-sdk.so"; constexpr auto rocprofiler_lib_register_entrypoint = "rocprofiler_set_api_table"; constexpr auto rocprofiler_register_lib_name = @@ -338,9 +339,8 @@ rocp_load_rocprofiler_lib(std::string _rocp_reg_lib) dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY); } - if(rocprofiler_register_verbose >= rocprofiler_register_info_level) - LOG(INFO) << "loaded " << _rocp_reg_lib_path_fname.string() << " library at " - << _rocp_reg_lib_path.string(); + LOG(INFO) << "loaded " << _rocp_reg_lib_path_fname.string() << " library at " + << _rocp_reg_lib_path.string(); LOG_IF(WARNING, rocprofiler_lib_handle == nullptr) << _rocp_reg_lib << " failed to load\n"; @@ -356,7 +356,7 @@ rocp_load_rocprofiler_lib(std::string _rocp_reg_lib) } constexpr auto library_seq = std::make_index_sequence{}; -auto global_mutex = std::recursive_mutex{}; +auto global_count = std::atomic{ 0 }; auto import_info = rocp_reg_get_imports(library_seq); auto instance_counters = std::array{}; } // namespace @@ -373,11 +373,33 @@ rocprofiler_register_library_api_table( { if(api_table_length < 1) return ROCP_REG_BAD_API_TABLE_LENGTH; - (void) lib_version; - (void) api_tables; + rocprofiler_register::logging::initialize(); - auto _lk = std::unique_lock{ global_mutex, std::defer_lock }; - if(_lk.owns_lock()) return ROCP_REG_DEADLOCK; + // rocprofiler-register is disabled via environment + if(!common::get_env("ROCPROFILER_REGISTER_ENABLED", true)) + { + LOG(INFO) << "rocprofiler-register disabled via ROCPROFILER_REGISTER_ENABLED=0"; + return ROCP_REG_NO_TOOLS; + } + + struct scoped_count + { + scoped_count() + : value{ ++global_count } + { } + + ~scoped_count() { --global_count; } + + scoped_count(const scoped_count&) = delete; + scoped_count(scoped_count&&) noexcept = delete; + scoped_count& operator=(const scoped_count&) = delete; + scoped_count& operator=(scoped_count&&) noexcept = delete; + + uint32_t value = 0; + }; + + auto _count = scoped_count{}; + if(_count.value > 1) return ROCP_REG_DEADLOCK; auto _scan_result = rocp_reg_scan_for_tools(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d0da1bcc22..bb4fb53ab2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -81,6 +81,11 @@ add_subdirectory(rocprofiler) # add_subdirectory(generic-tool) +# +# test app +# +add_subdirectory(bin) + # # common to multiple tests # diff --git a/tests/bin/CMakeLists.txt b/tests/bin/CMakeLists.txt new file mode 100644 index 0000000000..d655952445 --- /dev/null +++ b/tests/bin/CMakeLists.txt @@ -0,0 +1,108 @@ +# +# +# + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Threads REQUIRED) +find_package( + hip + HINTS + ${ROCM_PATH} + ENV + ROCM_PATH + /opt/rocm + PATHS + ${ROCM_PATH} + ENV + ROCM_PATH + /opt/rocm) + +if(hip_FOUND) + add_executable(simple-hip) + target_sources(simple-hip PRIVATE simple-hip.cpp) + target_compile_options(simple-hip PRIVATE -W -Wall -Wextra -Werror) + target_link_libraries(simple-hip PRIVATE Threads::Threads hip::host) + set(PRELOAD_TESTS_DISABLED OFF) +else() + add_executable(simple-hip EXCLUDE_FROM_ALL) + target_sources(simple-hip PRIVATE simple-hip.cpp) + target_link_libraries(simple-hip PRIVATE Threads::Threads) + set(PRELOAD_TESTS_DISABLED ON) +endif() + +# +# INSTALL +# +set(TEST_DESTDIR "${CMAKE_BINARY_DIR}/tests/install") +set(simple-hip-install-env "DESTDIR=${TEST_DESTDIR}") + +add_test( + NAME test-simple-hip-install + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target install --parallel 4 + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + +set_tests_properties( + test-simple-hip-install + PROPERTIES TIMEOUT + 120 + LABELS + "integration-test" + ENVIRONMENT + "${simple-hip-install-env}" + DISABLED + ${PRELOAD_TESTS_DISABLED} + FIXTURES_SETUP + "simple-hip-install") + +# +# NORMAL (no profiling library) +# +string(REPLACE "//" "/" TEST_INSTALL_PREFIX "${TEST_DESTDIR}/${CMAKE_INSTALL_PREFIX}") +set(simple-hip-normal-env + "LD_LIBRARY_PATH=${TEST_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}:${ROCM_PATH}/${CMAKE_INSTALL_LIBDIR}" + ) + +add_test(NAME test-simple-hip-normal COMMAND $) + +set_tests_properties( + test-simple-hip-normal + PROPERTIES TIMEOUT + 120 + LABELS + "integration-test" + ENVIRONMENT + "${simple-hip-normal-env}" + DEPENDS + test-simple-hip-install + DISABLED + ${PRELOAD_TESTS_DISABLED} + FIXTURES_SETUP + "simple-hip-works" + FIXTURES_REQUIRED + "simple-hip-install") + +# +# PRELOAD +# +set(simple-hip-preload-env ${simple-hip-normal-env} + "LD_PRELOAD=$") + +add_test(NAME test-simple-hip-preload COMMAND $) + +set_tests_properties( + test-simple-hip-preload + PROPERTIES TIMEOUT + 120 + LABELS + "integration-test" + ENVIRONMENT + "${simple-hip-preload-env}" + DEPENDS + test-simple-hip-install + DISABLED + ${PRELOAD_TESTS_DISABLED} + FIXTURES_REQUIRED + "simple-hip-install;simple-hip-works") diff --git a/tests/bin/simple-hip.cpp b/tests/bin/simple-hip.cpp new file mode 100644 index 0000000000..99ebe7cca2 --- /dev/null +++ b/tests/bin/simple-hip.cpp @@ -0,0 +1,174 @@ +// MIT License +// +// Copyright (c) 2023 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HIP_API_CALL(CALL) \ + if(hipError_t error_ = (CALL); error_ != hipSuccess) \ + { \ + auto _hip_api_print_lk = auto_lock_t{ print_lock }; \ + fprintf(stderr, \ + "%s:%d :: HIP error : %s\n", \ + __FILE__, \ + __LINE__, \ + hipGetErrorString(error_)); \ + fflush(stderr); \ + std::exit(EXIT_FAILURE); \ + } + +static constexpr int64_t Bi = 1; +static constexpr int64_t KiB = 1024 * Bi; +static constexpr int64_t MiB = 1024 * KiB; + +void +run(size_t rank, size_t tid, const char* prefix); + +namespace +{ +using auto_lock_t = std::unique_lock; +auto print_lock = std::mutex{}; +size_t xdim = 4960 * 2; +size_t ydim = 4960 * 2; +size_t nthreads = 2; +size_t nitr = 1; +} // namespace + +int +main(int argc, char** argv) +{ + for(int i = 1; i < argc; ++i) + { + auto _arg = std::string{ argv[i] }; + if(_arg == "?" || _arg == "-h" || _arg == "--help") + { + fprintf(stderr, + "usage: %s [M (%zu)] [N (%zu)] [NUM_THREADS (%zu)] [NUM_ITERATION " + "(%zu)]\n", + ::basename(argv[0]), + xdim, + ydim, + nthreads, + nitr); + exit(EXIT_SUCCESS); + } + } + + if(argc > 1) xdim = atoll(argv[1]); + if(argc > 2) ydim = atoll(argv[2]); + if(argc > 3) nthreads = atoll(argv[3]); + if(argc > 4) nitr = atoll(argv[4]); + + int ndevice = 0; + HIP_API_CALL(hipGetDeviceCount(&ndevice)); + + printf("[%s] Number of devices found: %i\n", ::basename(argv[0]), ndevice); + printf("[%s] Number of matrix: %zu x %zu\n", ::basename(argv[0]), xdim, ydim); + printf("[%s] Number of threads: %zu\n", ::basename(argv[0]), nthreads); + printf("[%s] Number of iterations: %zu\n", ::basename(argv[0]), nitr); + + for(size_t j = 0; j < nitr; ++j) + { + printf("\n[%s] Iteration #%zu\n\n", ::basename(argv[0]), j); + + auto threads = std::vector{}; + threads.reserve(nthreads); + + for(size_t i = 0; i < nthreads; ++i) + threads.emplace_back(run, getpid(), i, ::basename(argv[0])); + + for(auto& itr : threads) + itr.join(); + } + + return 0; +} + +template +auto +allocate_memory(size_t M, size_t N, Tp val) +{ + const auto sz = M * N; + const auto nb = sz * sizeof(Tp); + + Tp* ptr = new Tp[M * N]; + ::memset(ptr, val, nb); + + HIP_API_CALL(hipHostRegister(ptr, nb, hipHostRegisterDefault)) + + return ptr; +} + +template +auto +deallocate_memory(Tp* ptr) +{ + HIP_API_CALL(hipHostUnregister(ptr)) + delete[] ptr; +} + +void +run(size_t rank, size_t tid, const char* label) +{ + const auto M = xdim; + const auto N = ydim; + + auto* inp = allocate_memory(M, N, 0); + auto* out = allocate_memory(M, N, 1); + + auto _engine = + std::default_random_engine{ std::random_device{}() * (rank + 1) * (tid + 1) }; + std::uniform_int_distribution _dist{ 0, 1000 }; + + for(size_t i = 0; i < (M * N); i++) + inp[i] = _dist(_engine); + + // lock during malloc to get more accurate memory info + { + auto_lock_t _lk{ print_lock }; + size_t free_gpu_mem = 0; + size_t total_gpu_mem = 0; + + HIP_API_CALL(hipMemGetInfo(&free_gpu_mem, &total_gpu_mem)); + free_gpu_mem /= MiB; + total_gpu_mem /= MiB; + + std::cout << "[" << label << "][" << rank << "][" << tid + << "] Available GPU memory (MiB): " << std::setw(6) << free_gpu_mem + << " / " << std::setw(6) << total_gpu_mem << std::endl; + } + + deallocate_memory(inp); + deallocate_memory(out); +} From fc712350ef8ba1df3870dd8f8e9593bec1a5122e Mon Sep 17 00:00:00 2001 From: "Madsen, Jonathan" Date: Fri, 21 Mar 2025 04:36:58 -0500 Subject: [PATCH 37/49] Record loaded runtimes (#6) * Provide rocprofiler_register_iterate_registration_info function - stores the runtime arguments for later reference * Fix compilation error * Removed unused variable * Store api tables in vector * Update license * Replace global_mutex usage with scoped_count - in rocp_invoke_registrations * Formatting --------- Co-authored-by: Jonathan R. Madsen --- .../rocprofiler-register.h | 44 ++++ .../details/scope_destructor.hpp | 87 ++++++++ .../rocprofiler_register.cpp | 191 ++++++++++++++++-- tests/rocprofiler/CMakeLists.txt | 21 +- tests/rocprofiler/rocprofiler.cpp | 71 ++++++- 5 files changed, 386 insertions(+), 28 deletions(-) create mode 100644 source/lib/rocprofiler-register/details/scope_destructor.hpp diff --git a/source/include/rocprofiler-register/rocprofiler-register.h b/source/include/rocprofiler-register/rocprofiler-register.h index 79a89fd1b8..f6751a4f59 100644 --- a/source/include/rocprofiler-register/rocprofiler-register.h +++ b/source/include/rocprofiler-register/rocprofiler-register.h @@ -129,6 +129,50 @@ rocprofiler_register_library_api_table( const char* rocprofiler_register_error_string(rocprofiler_register_error_code_t) ROCPROFILER_REGISTER_PUBLIC_API; +/// @brief Struct containing the information about the libraries which have registered +/// with rocprofiler-register. @see rocprofiler_register_iterate_registration_info +typedef struct rocprofiler_register_registration_info_t +{ + size_t size; ///< in case of future extensions + const char* common_name; ///< name of the library + uint32_t lib_version; ///< version + uint64_t api_table_length; ///< number of API tables +} rocprofiler_register_registration_info_t; + +/** + * @brief Callback function for iterating over the libraries which have registered + * with rocprofiler-register. @see rocprofiler_register_iterate_registration_info + * + * @param [in] info Pointer to library registration instance. Invokee should make a copy + * for reference outside of callback. + * @param [in] data User data passed to ::rocprofiler_register_iterate_registration_info + * @return int + * @retval 0 If zero is returned from callback, rocprofiler-register will continue to next + * registration info, if one exists + * @retval -1 If -1 (or any value != 0) is returned from callback, rocprofiler-register + * will cease to iterate over the remaining registration info, if any exists + */ +typedef int (*rocprofiler_register_registration_info_cb_t)( + rocprofiler_register_registration_info_t* info, + void* data); + +/** + * @brief Iterates over all the (valid) libraries which registered their API tables with + * rocprofiler-register. Any libraries which do not have an accepted common name, have an + * invalid import function address (in secure mode), or have registered too many instances + * are not reported by this function. + * + * @param [in] callback Callback function to invoke for each valid registered library + * @param [in] data User data to pass to the callback function + * @return ::rocprofiler_register_error_code_t + * @retval ::ROCP_REG_SUCCESS Always returned + */ +rocprofiler_register_error_code_t +rocprofiler_register_iterate_registration_info( + rocprofiler_register_registration_info_cb_t callback, + void* data) + ROCPROFILER_REGISTER_ATTRIBUTE(nonnull(1)) ROCPROFILER_REGISTER_PUBLIC_API; + #ifdef __cplusplus } #endif diff --git a/source/lib/rocprofiler-register/details/scope_destructor.hpp b/source/lib/rocprofiler-register/details/scope_destructor.hpp new file mode 100644 index 0000000000..16ae37079f --- /dev/null +++ b/source/lib/rocprofiler-register/details/scope_destructor.hpp @@ -0,0 +1,87 @@ +// MIT License +// +// Copyright (c) 2025 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 "fmt/core.h" +#include "glog/logging.h" + +#include +#include + +namespace rocprofiler_register +{ +namespace common +{ +struct scope_destructor +{ + /// \fn scope_destructor(FuncT&& _fini, InitT&& _init) + /// \tparam FuncT "std::function or void (*)()" + /// \tparam InitT "std::function or void (*)()" + /// \param _fini Function to execute when object is destroyed + /// \param _init Function to execute when object is created (optional) + /// + /// \brief Provides a utility to perform an operation when exiting a scope. + template + scope_destructor( + FuncT&& _fini, + InitT&& _init = []() {}); + + ~scope_destructor() { m_functor(); } + + // delete copy operations + scope_destructor(const scope_destructor&) = delete; + scope_destructor& operator=(const scope_destructor&) = delete; + + // allow move operations + scope_destructor(scope_destructor&& rhs) noexcept; + scope_destructor& operator=(scope_destructor&& rhs) noexcept; + +private: + std::function m_functor = []() {}; +}; + +template +scope_destructor::scope_destructor(FuncT&& _fini, InitT&& _init) +: m_functor{ std::forward(_fini) } +{ + _init(); +} + +inline scope_destructor::scope_destructor(scope_destructor&& rhs) noexcept +: m_functor{ std::move(rhs.m_functor) } +{ + rhs.m_functor = []() {}; +} + +inline scope_destructor& +scope_destructor::operator=(scope_destructor&& rhs) noexcept +{ + if(this != &rhs) + { + m_functor = std::move(rhs.m_functor); + rhs.m_functor = []() {}; + } + return *this; +} +} // namespace common +} // namespace rocprofiler_register diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index ff95239ac0..b65985eb78 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -26,6 +26,7 @@ #include "details/environment.hpp" #include "details/filesystem.hpp" #include "details/logging.hpp" +#include "details/scope_destructor.hpp" #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +42,7 @@ #include #include +#include extern "C" { #pragma weak rocprofiler_configure @@ -247,7 +250,13 @@ auto rocp_reg_get_imports(std::index_sequence) rocp_set_api_table_data_t rocp_load_rocprofiler_lib(std::string _rocp_reg_lib); -auto +struct rocp_scan_data +{ + void* handle = nullptr; + rocprofiler_set_api_table_t set_api_table_fn = nullptr; +}; + +rocp_scan_data rocp_reg_scan_for_tools() { auto* _configure_func = dlsym(RTLD_DEFAULT, "rocprofiler_configure"); @@ -265,7 +274,7 @@ rocp_reg_scan_for_tools() if(_found_tool) { if(rocprofiler_lib_handle && rocprofiler_lib_config_fn) - return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn); + return rocp_scan_data{ rocprofiler_lib_handle, rocprofiler_lib_config_fn }; if(_rocp_reg_lib.empty()) _rocp_reg_lib = rocprofiler_lib_name; @@ -281,7 +290,7 @@ rocp_reg_scan_for_tools() rocprofiler_lib_config_fn = &rocprofiler_set_api_table; } - return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn); + return rocp_scan_data{ rocprofiler_lib_handle, rocprofiler_lib_config_fn }; } rocp_set_api_table_data_t @@ -355,10 +364,105 @@ rocp_load_rocprofiler_lib(std::string _rocp_reg_lib) return std::make_tuple(rocprofiler_lib_handle, rocprofiler_lib_config_fn); } +struct registered_library_api_table +{ + bool propagated = false; + const char* common_name = nullptr; + rocprofiler_register_import_func_t import_func = nullptr; + uint32_t lib_version = 0; + std::vector api_tables = {}; + uint64_t instance_value = 0; +}; + +constexpr auto instance_bits = sizeof(uint64_t) * 8; // bits in instance_counters +constexpr auto max_instances = instance_bits * ROCP_REG_LAST; constexpr auto library_seq = std::make_index_sequence{}; auto global_count = std::atomic{ 0 }; auto import_info = rocp_reg_get_imports(library_seq); auto instance_counters = std::array{}; +auto registered = + std::array, max_instances>{}; + +struct scoped_count +{ + scoped_count() + : value{ ++global_count } + { } + + ~scoped_count() { --global_count; } + + scoped_count(const scoped_count&) = delete; + scoped_count(scoped_count&&) noexcept = delete; + scoped_count& operator=(const scoped_count&) = delete; + scoped_count& operator=(scoped_count&&) noexcept = delete; + + uint32_t value = 0; +}; + +std::optional* +rocp_add_registered_library_api_table(const char* common_name, + rocprofiler_register_import_func_t import_func, + uint32_t lib_version, + void** api_tables, + uint64_t api_tables_len, + uint64_t instance_val) +{ + LOG(INFO) << fmt::format("rocprofiler-register library api table registration:\n\t-" + "name: {}\n\t- version: {}\n\t- # tables: {}", + common_name, + lib_version, + api_tables_len); + + for(auto& itr : registered) + { + if(!itr) + { + auto _tables = std::vector{}; + _tables.reserve(api_tables_len); + for(uint64_t i = 0; i < api_tables_len; ++i) + _tables.emplace_back(api_tables[i]); + + itr = registered_library_api_table{ + false, common_name, import_func, + lib_version, std::move(_tables), instance_val + }; + return &itr; + } + } + + return nullptr; +} + +rocprofiler_register_error_code_t +rocp_invoke_registrations(bool invoke_all) +{ + auto _count = scoped_count{}; + if(_count.value > 1) return ROCP_REG_DEADLOCK; + + for(auto& itr : registered) + { + if(itr && (!itr->propagated || invoke_all)) + { + auto _scan_result = rocp_reg_scan_for_tools(); + + // rocprofiler_set_api_table has been found and we have pass the API data + auto _activate_rocprofiler = (_scan_result.set_api_table_fn != nullptr); + + if(_activate_rocprofiler) + { + auto _ret = _scan_result.set_api_table_fn(itr->common_name, + itr->lib_version, + itr->instance_value, + itr->api_tables.data(), + itr->api_tables.size()); + if(_ret != 0) return ROCP_REG_ROCPROFILER_ERROR; + itr->propagated = true; + } + } + } + + return ROCP_REG_SUCCESS; +} } // namespace extern "C" { @@ -382,22 +486,6 @@ rocprofiler_register_library_api_table( return ROCP_REG_NO_TOOLS; } - struct scoped_count - { - scoped_count() - : value{ ++global_count } - { } - - ~scoped_count() { --global_count; } - - scoped_count(const scoped_count&) = delete; - scoped_count(scoped_count&&) noexcept = delete; - scoped_count& operator=(const scoped_count&) = delete; - scoped_count& operator=(scoped_count&&) noexcept = delete; - - uint32_t value = 0; - }; - auto _count = scoped_count{}; if(_count.value > 1) return ROCP_REG_DEADLOCK; @@ -464,17 +552,33 @@ rocprofiler_register_library_api_table( auto& _bits = *reinterpret_cast(®ister_id->handle); _bits = bitset_t{ (offset_factor * _import_match->library_idx) + _instance_val }; + auto* reginfo = rocp_add_registered_library_api_table(common_name, + import_func, + lib_version, + api_tables, + api_table_length, + _instance_val); + + LOG_IF(WARNING, !reginfo) << fmt::format( + "rocprofiler-register failed to create registration info for " + "{} version {} (instance {})", + common_name, + lib_version, + _instance_val); + if(_bits.to_ulong() != register_id->handle) throw std::runtime_error("error encoding register_id"); // rocprofiler library is dlopened and we have the functor to pass the API data - auto _activate_rocprofiler = (_scan_result.second != nullptr); + auto _activate_rocprofiler = (_scan_result.set_api_table_fn != nullptr); if(_activate_rocprofiler) { - auto _ret = _scan_result.second( + auto _ret = _scan_result.set_api_table_fn( common_name, lib_version, _instance_val, api_tables, api_table_length); if(_ret != 0) return ROCP_REG_ROCPROFILER_ERROR; + + if(reginfo) (*reginfo)->propagated = true; } else { @@ -490,4 +594,49 @@ rocprofiler_register_error_string(rocprofiler_register_error_code_t _ec) return rocprofiler_register_error_string( _ec, std::make_index_sequence{}); } + +rocprofiler_register_error_code_t +rocprofiler_register_iterate_registration_info( + rocprofiler_register_registration_info_cb_t callback, + void* data) +{ + for(const auto& itr : registered) + { + if(itr) + { + auto _info = rocprofiler_register_registration_info_t{ + .size = sizeof(rocprofiler_register_registration_info_t), + .common_name = itr->common_name, + .lib_version = itr->lib_version, + .api_table_length = itr->api_tables.size() + }; + // invoke callback and break if the caller does not return zero + if(callback(&_info, data) != ROCP_REG_SUCCESS) break; + } + } + + return ROCP_REG_SUCCESS; +} + +rocprofiler_register_error_code_t +rocprofiler_register_invoke_nonpropagated_registrations() ROCPROFILER_REGISTER_PUBLIC_API; + +// +// This function can be invoked by ptrace +rocprofiler_register_error_code_t +rocprofiler_register_invoke_nonpropagated_registrations() +{ + return rocp_invoke_registrations(false); +} + +rocprofiler_register_error_code_t +rocprofiler_register_invoke_all_registrations() ROCPROFILER_REGISTER_PUBLIC_API; + +// +// This function can be invoked by ptrace +rocprofiler_register_error_code_t +rocprofiler_register_invoke_all_registrations() +{ + return rocp_invoke_registrations(true); +} } diff --git a/tests/rocprofiler/CMakeLists.txt b/tests/rocprofiler/CMakeLists.txt index 59a84a11bf..6be6a04534 100644 --- a/tests/rocprofiler/CMakeLists.txt +++ b/tests/rocprofiler/CMakeLists.txt @@ -1,11 +1,28 @@ # # mock rocprofiler library # + +find_package(rocprofiler-register REQUIRED) +if(TARGET rocprofiler-register::rocprofiler-register-headers) + get_property( + rocp_reg_INCLUDE_DIR + TARGET rocprofiler-register::rocprofiler-register-headers + PROPERTY INTERFACE_INCLUDE_DIRECTORIES) +else() + get_property( + rocp_reg_INCLUDE_DIR + TARGET rocprofiler-register::rocprofiler-register + PROPERTY INTERFACE_INCLUDE_DIRECTORIES) +endif() + add_library(rocprofiler SHARED) add_library(rocprofiler::rocprofiler ALIAS rocprofiler) target_sources(rocprofiler PRIVATE rocprofiler.cpp) -target_include_directories(rocprofiler PUBLIC $ - $) +target_include_directories( + rocprofiler + PUBLIC $ + $ + $) set_target_properties( rocprofiler PROPERTIES OUTPUT_NAME rocprofiler-sdk diff --git a/tests/rocprofiler/rocprofiler.cpp b/tests/rocprofiler/rocprofiler.cpp index eac61cadff..c513f805dd 100644 --- a/tests/rocprofiler/rocprofiler.cpp +++ b/tests/rocprofiler/rocprofiler.cpp @@ -1,4 +1,5 @@ +#include #include #include #include @@ -8,8 +9,11 @@ #include #include +#include #include #include +#include +#include #ifndef ROCP_REG_FILE_NAME # define ROCP_REG_FILE_NAME \ @@ -64,6 +68,26 @@ roctx_range_pop(const char* name) { printf("[%s][pop] %s\n", ROCP_REG_FILE_NAME, name); } + +using reginfo_vec_t = std::vector; + +bool +check_registration_info(const char* name, + uint64_t lib_version, + uint64_t num_tables, + const reginfo_vec_t& infovec) +{ + for(const auto& itr : infovec) + { + if(std::string_view{ name } == std::string_view{ itr.common_name }) + { + return std::tie(lib_version, num_tables) == + std::tie(itr.lib_version, itr.api_table_length); + } + } + + return false; +} } // namespace rocprofiler extern "C" { @@ -99,6 +123,34 @@ rocprofiler_set_api_table(const char* name, " did not contain rocprofiler_configure symbol" }; } + auto registration_info = ::rocprofiler::reginfo_vec_t{}; + { + auto* _handle = + dlopen("librocprofiler-register.so", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); + if(!_handle) + throw std::runtime_error{ + "error opening librocprofiler-register.so library " + }; + auto* _sym = dlsym(_handle, "rocprofiler_register_iterate_registration_info"); + if(!_sym) + throw std::runtime_error{ + "librocprofiler-register.so did not contain " + "rocprofiler_register_iterate_registration_info symbol" + }; + + auto _func = [](rocprofiler_register_registration_info_t* _info, + void* _vdata) -> int { + auto* _vec = static_cast<::rocprofiler::reginfo_vec_t*>(_vdata); + _vec->emplace_back(*_info); + return 0; + }; + + auto iterate_registration_info = + reinterpret_cast( + _sym); + iterate_registration_info(_func, ®istration_info); + } + using hip_table_t = hip::HipApiTable; using hsa_table_t = hsa::HsaApiTable; using roctx_table_t = roctx::ROCTxApiTable; @@ -121,23 +173,23 @@ rocprofiler_set_api_table(const char* name, if(std::string_view{ name } == "hip") { hip_table_t* _table = static_cast(tables[0]); - _table->hip_init_fn = &rocprofiler::hip_init; + _table->hip_init_fn = &::rocprofiler::hip_init; } else if(std::string_view{ name } == "hsa") { hsa_table_t* _table = static_cast(tables[0]); - _table->hsa_init_fn = &rocprofiler::hsa_init; + _table->hsa_init_fn = &::rocprofiler::hsa_init; } else if(std::string_view{ name } == "roctx") { roctx_table_t* _table = static_cast(tables[0]); - _table->roctxRangePush_fn = &rocprofiler::roctx_range_push; - _table->roctxRangePop_fn = &rocprofiler::roctx_range_pop; + _table->roctxRangePush_fn = &::rocprofiler::roctx_range_push; + _table->roctxRangePop_fn = &::rocprofiler::roctx_range_pop; } else if(std::string_view{ name } == "rccl") { rccl_table_t* _table = static_cast(tables[0]); - _table->ncclGetVersion_fn = &rocprofiler::ncclGetVersion; + _table->ncclGetVersion_fn = &::rocprofiler::ncclGetVersion; } else if(std::string_view{ name } == "rocdecode") { @@ -151,6 +203,15 @@ rocprofiler_set_api_table(const char* name, } } + if(!::rocprofiler::check_registration_info( + name, lib_version, num_tables, registration_info)) + { + auto ss = std::stringstream{}; + ss << "no matching registration info for " << name << " " + << " version " << lib_version << " (# tables = " << num_tables << ")"; + throw std::runtime_error{ ss.str() }; + } + return 0; } } From 9338b9abc330f7f17f6f6b20f0bef21fd1165803 Mon Sep 17 00:00:00 2001 From: "Madsen, Jonathan" Date: Sat, 22 Mar 2025 22:30:55 -0500 Subject: [PATCH 38/49] Remove rocprofiler-sdk forward decls from public header (#8) Co-authored-by: Jonathan R. Madsen --- .../rocprofiler-register.h | 21 ------------------- .../rocprofiler_register.cpp | 21 +++++++++++++++++++ tests/generic-tool/generic-tool.cpp | 4 ++-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/source/include/rocprofiler-register/rocprofiler-register.h b/source/include/rocprofiler-register/rocprofiler-register.h index f6751a4f59..52872cfb00 100644 --- a/source/include/rocprofiler-register/rocprofiler-register.h +++ b/source/include/rocprofiler-register/rocprofiler-register.h @@ -29,27 +29,6 @@ extern "C" { #endif -typedef struct -{ - const char* name; ///< clients should set this value for debugging - const uint32_t handle; ///< internal handle -} rocprofiler_client_id_t; - -typedef void (*rocprofiler_client_finalize_t)(rocprofiler_client_id_t); - -typedef int (*rocprofiler_tool_initialize_t)(rocprofiler_client_finalize_t finalize_func, - void* tool_data); - -typedef void (*rocprofiler_tool_finalize_t)(void* tool_data); - -typedef struct -{ - size_t size; ///< in case of future extensions - rocprofiler_tool_initialize_t initialize; ///< context creation - rocprofiler_tool_finalize_t finalize; ///< cleanup - void* tool_data; ///< data to provide to init and fini callbacks -} rocprofiler_tool_configure_result_t; - typedef uint32_t (*rocprofiler_register_import_func_t)(void); typedef struct diff --git a/source/lib/rocprofiler-register/rocprofiler_register.cpp b/source/lib/rocprofiler-register/rocprofiler_register.cpp index b65985eb78..df9631e08a 100644 --- a/source/lib/rocprofiler-register/rocprofiler_register.cpp +++ b/source/lib/rocprofiler-register/rocprofiler_register.cpp @@ -56,6 +56,27 @@ extern "C" { #pragma weak rocprofiler_register_import_roctx #pragma weak rocprofiler_register_import_roctx_static +typedef struct rocprofiler_client_id_t +{ + const char* name; ///< clients should set this value for debugging + const uint32_t handle; ///< internal handle +} rocprofiler_client_id_t; + +typedef void (*rocprofiler_client_finalize_t)(rocprofiler_client_id_t); + +typedef int (*rocprofiler_tool_initialize_t)(rocprofiler_client_finalize_t finalize_func, + void* tool_data); + +typedef void (*rocprofiler_tool_finalize_t)(void* tool_data); + +typedef struct rocprofiler_tool_configure_result_t +{ + size_t size; ///< in case of future extensions + rocprofiler_tool_initialize_t initialize; ///< context creation + rocprofiler_tool_finalize_t finalize; ///< cleanup + void* tool_data; ///< data to provide to init and fini callbacks +} rocprofiler_tool_configure_result_t; + extern rocprofiler_tool_configure_result_t* rocprofiler_configure(uint32_t, const char*, uint32_t, rocprofiler_client_id_t*); diff --git a/tests/generic-tool/generic-tool.cpp b/tests/generic-tool/generic-tool.cpp index 3ee4c7800d..d9e2bd5c60 100644 --- a/tests/generic-tool/generic-tool.cpp +++ b/tests/generic-tool/generic-tool.cpp @@ -5,7 +5,7 @@ #include extern "C" { -typedef struct +typedef struct rocprofiler_client_id_t { const char* name; ///< clients should set this value for debugging const uint32_t handle; ///< internal handle @@ -18,7 +18,7 @@ typedef int (*rocprofiler_tool_initialize_t)(rocprofiler_client_finalize_t final typedef void (*rocprofiler_tool_finalize_t)(void* tool_data); -typedef struct +typedef struct rocprofiler_tool_configure_result_t { size_t size; ///< in case of future extensions rocprofiler_tool_initialize_t initialize; ///< context creation From 603038d4d65f67d30134b2bedf124cb80a75cc52 Mon Sep 17 00:00:00 2001 From: "Mallya, Ameya Keshava" Date: Mon, 31 Mar 2025 13:35:09 -0700 Subject: [PATCH 39/49] Adding !verify features --- .github/workflows/rocm_ci_caller.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/rocm_ci_caller.yml b/.github/workflows/rocm_ci_caller.yml index 5373d66535..0e3d93bd95 100644 --- a/.github/workflows/rocm_ci_caller.yml +++ b/.github/workflows/rocm_ci_caller.yml @@ -1,25 +1,25 @@ -name: ROCm CI Caller - +name: ROCm CI Caller on: pull_request: branches: [amd-staging, release/rocm-rel-*] types: [opened, reopened, synchronize] push: branches: [amd-mainline] - workflow_dispatch: + workflow_dispatch: issue_comment: - types: [created] + types: [created] jobs: call-workflow: - if: ${{ github.event_name != 'issue_comment' || github.event.comment.body == '!verify' }} - uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/rocm_ci.yml@mainline + if: github.event_name != 'issue_comment' ||(github.event_name == 'issue_comment' && github.event.issue.pull_request && (startsWith(github.event.comment.body, '!verify') || startsWith(github.event.comment.body, '!verify release') || startsWith(github.event.comment.body, '!verify retest'))) + uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/rocm_ci.yml@verifyfunc secrets: inherit with: - input_sha: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} - input_pr_num: ${{ github.event_name == 'pull_request' && github.event.pull_request.number || 0 }} - input_pr_url: ${{ github.event_name == 'pull_request' && github.event.pull_request.html_url || '' }} - input_pr_title: ${{ github.event_name == 'pull_request' && github.event.pull_request.title || '' }} + input_sha: ${{github.event_name == 'pull_request' && github.event.pull_request.head.sha || (github.event_name == 'push' && github.sha) || (github.event_name == 'issue_comment' && github.event.issue.pull_request.head.sha) || github.sha}} + input_pr_num: ${{github.event_name == 'pull_request' && github.event.pull_request.number || (github.event_name == 'issue_comment' && github.event.issue.number) || 0}} + input_pr_url: ${{github.event_name == 'pull_request' && github.event.pull_request.html_url || (github.event_name == 'issue_comment' && github.event.issue.pull_request.html_url) || ''}} + input_pr_title: ${{github.event_name == 'pull_request' && github.event.pull_request.title || (github.event_name == 'issue_comment' && github.event.issue.pull_request.title) || ''}} repository_name: ${{ github.repository }} - base_ref: ${{ github.event_name == 'pull_request' && github.base_ref || github.ref }} - trigger_event_type: ${{ github.event_name }} + base_ref: ${{github.event_name == 'pull_request' && github.event.pull_request.base.ref || (github.event_name == 'issue_comment' && github.event.issue.pull_request.base.ref) || github.ref}} + trigger_event_type: ${{ github.event_name }} + comment_text: ${{ github.event_name == 'issue_comment' && github.event.comment.body || '' }} From b96aab5b36a9fe9afad5a6472f873307939dba5c Mon Sep 17 00:00:00 2001 From: "Mallya, Ameya Keshava" Date: Tue, 1 Apr 2025 09:47:28 -0700 Subject: [PATCH 40/49] Fix to mainline --- .github/workflows/rocm_ci_caller.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rocm_ci_caller.yml b/.github/workflows/rocm_ci_caller.yml index 0e3d93bd95..0311611426 100644 --- a/.github/workflows/rocm_ci_caller.yml +++ b/.github/workflows/rocm_ci_caller.yml @@ -12,7 +12,7 @@ on: jobs: call-workflow: if: github.event_name != 'issue_comment' ||(github.event_name == 'issue_comment' && github.event.issue.pull_request && (startsWith(github.event.comment.body, '!verify') || startsWith(github.event.comment.body, '!verify release') || startsWith(github.event.comment.body, '!verify retest'))) - uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/rocm_ci.yml@verifyfunc + uses: AMD-ROCm-Internal/rocm_ci_infra/.github/workflows/rocm_ci.yml@mainline secrets: inherit with: input_sha: ${{github.event_name == 'pull_request' && github.event.pull_request.head.sha || (github.event_name == 'push' && github.sha) || (github.event_name == 'issue_comment' && github.event.issue.pull_request.head.sha) || github.sha}} From 1b0ce8009202ab11181cf09eca06158ec6f2f31b Mon Sep 17 00:00:00 2001 From: "Hila, Nino" Date: Wed, 23 Apr 2025 22:05:36 -0400 Subject: [PATCH 41/49] Add palamida.yml (#9) --- .github/palamida.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/palamida.yml diff --git a/.github/palamida.yml b/.github/palamida.yml new file mode 100644 index 0000000000..c34f60c67f --- /dev/null +++ b/.github/palamida.yml @@ -0,0 +1,6 @@ +disabled: false +scmId: gh-emu-rocm +branchesToScan: + - amd-staging + - amd-mainline +jenkinsUrl: https://palamidajenkinsvm.amd.com/job/palamida/job/pci/job/ScanInitiatorGitHub \ No newline at end of file From 16b142bb31ab596431b25d6d1715488c8e245b23 Mon Sep 17 00:00:00 2001 From: "Elwazir, Ammar" Date: Wed, 23 Apr 2025 21:06:02 -0500 Subject: [PATCH 42/49] Removing deprecated Ubuntu 20.04 runner (#11) --- .github/workflows/continuous-integration.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index b437726573..683b572906 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -32,14 +32,6 @@ jobs: compiler: 'clang-15' ci-args: '--linter clang-tidy' ci-tag: '-clang-tidy' - - runner: 'ubuntu-20.04' - compiler: 'gcc-9' - ci-args: '' - ci-tag: '' - - runner: 'ubuntu-20.04' - compiler: 'clang-10' - ci-args: '' - ci-tag: '' - runner: 'ubuntu-22.04' compiler: 'clang-13' ci-args: '' From 4427f2bd6d492319b4a487811d168b8257693071 Mon Sep 17 00:00:00 2001 From: "Bhardwaj, Gopesh" Date: Wed, 30 Apr 2025 09:57:37 +0530 Subject: [PATCH 43/49] updating fmt submodule to latest release tag (#13) * updating fmt submodule to latest release tag * fix configuration error --- cmake/rocprofiler_register_config_packaging.cmake | 2 +- external/fmt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/rocprofiler_register_config_packaging.cmake b/cmake/rocprofiler_register_config_packaging.cmake index 5e98f3e53a..da8bbc8b90 100644 --- a/cmake/rocprofiler_register_config_packaging.cmake +++ b/cmake/rocprofiler_register_config_packaging.cmake @@ -34,7 +34,7 @@ get_cmake_property(ROCPROFILER_REGISTER_PACKAGING_COMPONENTS COMPONENTS) rocprofiler_register_add_feature(ROCPROFILER_REGISTER_PACKAGING_COMPONENTS "Packaging components") list(REMOVE_ITEM ROCPROFILER_REGISTER_PACKAGING_COMPONENTS "Development" "Unspecified" - "external") + "external" "fmt-core") list(LENGTH ROCPROFILER_REGISTER_PACKAGING_COMPONENTS NUM_ROCPROFILER_REGISTER_PACKAGING_COMPONENTS) diff --git a/external/fmt b/external/fmt index 6c845f57e5..123913715a 160000 --- a/external/fmt +++ b/external/fmt @@ -1 +1 @@ -Subproject commit 6c845f57e5db589208ff0c2808238587cafafa82 +Subproject commit 123913715afeb8a437e6388b4473fcc4753e1c9a From 831f002fbc9ea2510c77cd9ba4f821a81f35cc0e Mon Sep 17 00:00:00 2001 From: "Hila, Nino" Date: Tue, 13 May 2025 00:52:24 -0400 Subject: [PATCH 44/49] Update palamida.yml (#14) * Add palamida.yml - removing url --- .github/palamida.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/palamida.yml b/.github/palamida.yml index c34f60c67f..47bd57a5ab 100644 --- a/.github/palamida.yml +++ b/.github/palamida.yml @@ -2,5 +2,4 @@ disabled: false scmId: gh-emu-rocm branchesToScan: - amd-staging - - amd-mainline -jenkinsUrl: https://palamidajenkinsvm.amd.com/job/palamida/job/pci/job/ScanInitiatorGitHub \ No newline at end of file + - amd-mainline \ No newline at end of file From 19fe192e8fe64ec509962afe8f6e452680dcf739 Mon Sep 17 00:00:00 2001 From: "Trowbridge, Ian" Date: Tue, 17 Jun 2025 10:34:21 -0500 Subject: [PATCH 45/49] Add copyright disclaimer for new files (#16) --- tests/rocdecode/rocdecode.cpp | 22 ++++++++++++++++++++++ tests/rocdecode/rocdecode.hpp | 22 ++++++++++++++++++++++ tests/rocjpeg/rocjpeg.cpp | 22 ++++++++++++++++++++++ tests/rocjpeg/rocjpeg.hpp | 22 ++++++++++++++++++++++ 4 files changed, 88 insertions(+) diff --git a/tests/rocdecode/rocdecode.cpp b/tests/rocdecode/rocdecode.cpp index 3a99fe04ff..ac28875d2b 100644 --- a/tests/rocdecode/rocdecode.cpp +++ b/tests/rocdecode/rocdecode.cpp @@ -1,3 +1,25 @@ +// MIT License +// +// Copyright (c) 2023-2025 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 "rocdecode.hpp" #include diff --git a/tests/rocdecode/rocdecode.hpp b/tests/rocdecode/rocdecode.hpp index e1706e939d..37f499eb92 100644 --- a/tests/rocdecode/rocdecode.hpp +++ b/tests/rocdecode/rocdecode.hpp @@ -1,3 +1,25 @@ +// MIT License +// +// Copyright (c) 2023-2025 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 ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION 0 diff --git a/tests/rocjpeg/rocjpeg.cpp b/tests/rocjpeg/rocjpeg.cpp index e77944439a..a04a3052fd 100644 --- a/tests/rocjpeg/rocjpeg.cpp +++ b/tests/rocjpeg/rocjpeg.cpp @@ -1,3 +1,25 @@ +// MIT License +// +// Copyright (c) 2023-2025 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 "rocjpeg.hpp" #include diff --git a/tests/rocjpeg/rocjpeg.hpp b/tests/rocjpeg/rocjpeg.hpp index dbd053b2ef..2dc6911bcc 100644 --- a/tests/rocjpeg/rocjpeg.hpp +++ b/tests/rocjpeg/rocjpeg.hpp @@ -1,3 +1,25 @@ +// MIT License +// +// Copyright (c) 2023-2025 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 ROCDECODE_RUNTIME_API_TABLE_MAJOR_VERSION 0 From 03d58213b913944e3497112f7f16c51122ef8ee8 Mon Sep 17 00:00:00 2001 From: "Vaddireddy, Sushma" Date: Fri, 20 Jun 2025 11:54:40 -0700 Subject: [PATCH 46/49] Added install target for simple-hip executable (#10) * Added install target for simple-hip executable * Updating destination path * Update CMakeLists.txt * Update CMakeLists.txt * Test Installed Packages * Updating Destination path * Update continuous-integration.yml * Update continuous-integration.yml * Adding env * Adding PACKAGING_INSTALL_PREFIX * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Update continuous-integration.yml * Add libasan.so path for AddressSanitizer preloadiing * Add libasan.so path for AddressSanitizer preloadiing * Add libasan.so path for test test-simple-hip-normal * Added sanitizer runtime library for tests * Added LD_PRELOAD to simple-hip-normal-env test * Added LD_PRELOAD to simple-hip-normal-env test * Update CMakeLists.txt * Update CMakeLists.txt * Update CMakeLists.txt * Formatting * Updated path for simple-hip-preload-env * Updated path for simple-hip-preload-env * Update continuous-integration.yml * Updated preload path for simple-hip-preload-env * Updated preload path for simple-hip-preload-env --------- Co-authored-by: Sushma Vaddireddy Co-authored-by: Elwazir, Ammar --- .github/workflows/continuous-integration.yml | 49 ++++++++++---------- tests/bin/CMakeLists.txt | 12 +++-- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 683b572906..05b98a4460 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -19,41 +19,33 @@ jobs: strategy: fail-fast: false matrix: - runner: ['ubuntu-latest'] compiler: ['clang-14', 'clang-15', 'gcc-11', 'gcc-12'] ci-args: [''] ci-tag: [''] include: - - runner: 'ubuntu-latest' - compiler: 'gcc-12' + - compiler: 'gcc-12' ci-args: '--coverage' ci-tag: '-codecov' - - runner: 'ubuntu-latest' - compiler: 'clang-15' + - compiler: 'clang-15' ci-args: '--linter clang-tidy' ci-tag: '-clang-tidy' - - runner: 'ubuntu-22.04' - compiler: 'clang-13' + - compiler: 'clang-13' ci-args: '' ci-tag: '' - - runner: 'ubuntu-22.04' - compiler: 'gcc-12' + - compiler: 'gcc-12' ci-args: '--memcheck ThreadSanitizer' ci-tag: '-thread-sanitizer' - - runner: 'ubuntu-22.04' - compiler: 'gcc-12' + - compiler: 'gcc-12' ci-args: '--memcheck AddressSanitizer' ci-tag: '-address-sanitizer' - - runner: 'ubuntu-22.04' - compiler: 'gcc-12' + - compiler: 'gcc-12' ci-args: '--memcheck LeakSanitizer' ci-tag: '-leak-sanitizer' - # - runner: 'ubuntu-latest' - # compiler: 'gcc-12' + # - compiler: 'gcc-12' # ci-args: '--memcheck UndefinedBehaviorSanitizer' # ci-tag: '-undefined-behavior-sanitizer' - runs-on: ${{ matrix.runner }} + runs-on: rocprof-azure-emu-runner-set env: BUILD_TYPE: RelWithDebInfo @@ -68,10 +60,10 @@ jobs: run: | CC=${{ matrix.compiler }} && CXX=$(echo ${{ matrix.compiler }} | sed 's/clang-/clang++-/1' | sed 's/gcc-/g++-/1') && - sudo apt-get update && - sudo apt-get install -y build-essential python3 environment-modules ${{ matrix.compiler }} ${CXX} && - sudo update-alternatives --install /usr/bin/cc cc /usr/bin/${CC} 100 && - sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/${CXX} 100 && + apt-get update && + apt-get install -y build-essential python3 environment-modules ${{ matrix.compiler }} ${CXX} && + update-alternatives --install /usr/bin/cc cc /usr/bin/${CC} 100 && + update-alternatives --install /usr/bin/c++ c++ /usr/bin/${CXX} 100 && python3 -m pip install --upgrade pip && python3 -m pip install 'cmake==3.22.0' && python3 -m pip install -r requirements.txt @@ -80,14 +72,14 @@ jobs: timeout-minutes: 25 if: ${{ matrix.compiler == 'gcc-12' }} run: | - sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-12 100 + update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-12 100 - name: Setup Clang-Tidy timeout-minutes: 25 if: ${{ matrix.compiler == 'clang-15' }} run: | - sudo apt-get install -y clang-tidy-15 - sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-15 100 + apt-get install -y clang-tidy-15 + update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-15 100 - name: Configure, Build, and Test timeout-minutes: 115 @@ -95,7 +87,7 @@ jobs: run: cmake --version && python3 ./scripts/run-ci.py -B build - --name ${{ github.repository_owner }}-${{ github.ref_name }}-${{ matrix.runner }}-${{ matrix.compiler }}${{ matrix.ci-tag }} + --name ${{ github.repository_owner }}-${{ github.ref_name }}-azure-mi300x-${{ matrix.compiler }}${{ matrix.ci-tag }} --build-jobs 2 --site GitHub ${{ matrix.ci-args }} @@ -122,6 +114,15 @@ jobs: mkdir -p ${{ env.PACKAGING_INSTALL_PREFIX }} ./rocprofiler-register-*-Linux.sh --prefix=${{ env.PACKAGING_INSTALL_PREFIX }} --exclude-subdir --skip-license + - name: Test Installed Packages + if: ${{ contains(matrix.compiler, 'clang-15') }} + timeout-minutes: 10 + shell: bash + run: | + CMAKE_PREFIX_PATH=/opt/rocm cmake -B build-tests-deb /opt/rocm/share/rocprofiler-register/tests + cmake --build build-tests-deb --target all --parallel 16 + ctest --test-dir build-tests-deb --output-on-failure + - name: Test Install Modulefile timeout-minutes: 15 shell: bash diff --git a/tests/bin/CMakeLists.txt b/tests/bin/CMakeLists.txt index d655952445..6e6825ee78 100644 --- a/tests/bin/CMakeLists.txt +++ b/tests/bin/CMakeLists.txt @@ -26,6 +26,10 @@ if(hip_FOUND) target_compile_options(simple-hip PRIVATE -W -Wall -Wextra -Werror) target_link_libraries(simple-hip PRIVATE Threads::Threads hip::host) set(PRELOAD_TESTS_DISABLED OFF) + install( + TARGETS simple-hip + DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/tests/bin + COMPONENT tests) else() add_executable(simple-hip EXCLUDE_FROM_ALL) target_sources(simple-hip PRIVATE simple-hip.cpp) @@ -63,7 +67,7 @@ set_tests_properties( string(REPLACE "//" "/" TEST_INSTALL_PREFIX "${TEST_DESTDIR}/${CMAKE_INSTALL_PREFIX}") set(simple-hip-normal-env "LD_LIBRARY_PATH=${TEST_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}:${ROCM_PATH}/${CMAKE_INSTALL_LIBDIR}" - ) + "LD_PRELOAD=${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_LIBRARY}") add_test(NAME test-simple-hip-normal COMMAND $) @@ -87,8 +91,10 @@ set_tests_properties( # # PRELOAD # -set(simple-hip-preload-env ${simple-hip-normal-env} - "LD_PRELOAD=$") +set(simple-hip-preload-env + ${simple-hip-normal-env} + "LD_PRELOAD=${ROCPROFILER_REGISTER_MEMCHECK_PRELOAD_LIBRARY}:$" + ) add_test(NAME test-simple-hip-preload COMMAND $) From 57143911c37069889845a63dd7e69ac710e6f6d9 Mon Sep 17 00:00:00 2001 From: "Elwazir, Ammar" Date: Mon, 30 Jun 2025 15:24:13 -0500 Subject: [PATCH 47/49] Update sync-staging.yaml --- .github/workflows/sync-staging.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sync-staging.yaml b/.github/workflows/sync-staging.yaml index 2e3ce6dd1b..56892d7224 100644 --- a/.github/workflows/sync-staging.yaml +++ b/.github/workflows/sync-staging.yaml @@ -1,12 +1,13 @@ name: Sync amd-staging to public repository on: + workflow_dispatch: push: branches: [ amd-staging ] jobs: git-mirror: - runs-on: ubuntu-latest + runs-on: rocprof-azure-docker-emu-runner-set steps: - name: git-sync uses: AMD-ROCm-Internal/rocprofiler-github-actions@git-sync-v3 From 80fcffeb5aaa1033d250f1d8e14fa9e387fc783b Mon Sep 17 00:00:00 2001 From: "Elwazir, Ammar" Date: Mon, 30 Jun 2025 15:24:35 -0500 Subject: [PATCH 48/49] Update sync-mainline.yaml --- .github/workflows/sync-mainline.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sync-mainline.yaml b/.github/workflows/sync-mainline.yaml index 33c4315c02..f4ab9230c7 100644 --- a/.github/workflows/sync-mainline.yaml +++ b/.github/workflows/sync-mainline.yaml @@ -1,12 +1,13 @@ name: Sync amd-mainline to public repository on: + workflow_dispatch: push: branches: [ amd-mainline ] jobs: git-mirror: - runs-on: ubuntu-latest + runs-on: rocprof-azure-docker-emu-runner-set steps: - name: git-sync uses: AMD-ROCm-Internal/rocprofiler-github-actions@git-sync-v3 From 37d7d920364c8b10ab592ff79e1c6811d114e6fa Mon Sep 17 00:00:00 2001 From: "Elwazir, Ammar" Date: Wed, 9 Jul 2025 11:50:41 -0500 Subject: [PATCH 49/49] Update Runners (#20) * Update continuous-integration.yml * Update formatting.yml * Update sync-mainline.yaml * Update sync-staging.yaml * Update continuous-integration.yml * Update formatting.yml * Update continuous-integration.yml * Update continuous-integration.yml --- .github/workflows/formatting.yml | 7 ++++--- .github/workflows/sync-mainline.yaml | 2 +- .github/workflows/sync-staging.yaml | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index c8030700b3..789698c620 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -16,7 +16,7 @@ concurrency: jobs: cmake: - runs-on: ubuntu-22.04 + runs-on: AMD-ROCm-Internal-dev1 steps: - uses: actions/checkout@v3 @@ -47,7 +47,8 @@ jobs: fi source: - runs-on: ubuntu-22.04 + runs-on: AMD-ROCm-Internal-dev1 + container: rocm/dev-ubuntu-22.04:latest steps: - uses: actions/checkout@v3 @@ -79,7 +80,7 @@ jobs: fi python: - runs-on: ubuntu-22.04 + runs-on: AMD-ROCm-Internal-dev1 strategy: matrix: python-version: ['3.10'] diff --git a/.github/workflows/sync-mainline.yaml b/.github/workflows/sync-mainline.yaml index f4ab9230c7..aa8e487185 100644 --- a/.github/workflows/sync-mainline.yaml +++ b/.github/workflows/sync-mainline.yaml @@ -7,7 +7,7 @@ on: jobs: git-mirror: - runs-on: rocprof-azure-docker-emu-runner-set + runs-on: AMD-ROCm-Internal-dev1 steps: - name: git-sync uses: AMD-ROCm-Internal/rocprofiler-github-actions@git-sync-v3 diff --git a/.github/workflows/sync-staging.yaml b/.github/workflows/sync-staging.yaml index 56892d7224..2fc355b94f 100644 --- a/.github/workflows/sync-staging.yaml +++ b/.github/workflows/sync-staging.yaml @@ -7,7 +7,7 @@ on: jobs: git-mirror: - runs-on: rocprof-azure-docker-emu-runner-set + runs-on: AMD-ROCm-Internal-dev1 steps: - name: git-sync uses: AMD-ROCm-Internal/rocprofiler-github-actions@git-sync-v3