From cbe3d1341619fb84c66ef8b2ed93811360c96be0 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 25 Nov 2024 17:49:29 +0100 Subject: [PATCH 1/4] Thread-safe lazy initialization pattern --- ddprof-lib/src/main/cpp/libraries.cpp | 2 -- ddprof-lib/src/main/cpp/libraries.h | 11 ++++++++--- ddprof-lib/src/main/cpp/livenessTracker.cpp | 1 - ddprof-lib/src/main/cpp/livenessTracker.h | 10 +++++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ddprof-lib/src/main/cpp/libraries.cpp b/ddprof-lib/src/main/cpp/libraries.cpp index 31be6fab5..787f6b848 100644 --- a/ddprof-lib/src/main/cpp/libraries.cpp +++ b/ddprof-lib/src/main/cpp/libraries.cpp @@ -5,8 +5,6 @@ #include "vmEntry.h" #include "vmStructs.h" -Libraries* Libraries::_instance = new Libraries(); - void Libraries::mangle(const char *name, char *buf, size_t size) { char *buf_end = buf + size; strcpy(buf, "_ZN"); diff --git a/ddprof-lib/src/main/cpp/libraries.h b/ddprof-lib/src/main/cpp/libraries.h index db7a1cd8a..b2422c6a1 100644 --- a/ddprof-lib/src/main/cpp/libraries.h +++ b/ddprof-lib/src/main/cpp/libraries.h @@ -5,8 +5,6 @@ class Libraries { private: - static Libraries * _instance; - CodeCacheArray _native_libs; CodeCache _runtime_stubs; @@ -21,7 +19,14 @@ class Libraries { CodeCache *findLibraryByName(const char *lib_name); CodeCache *findLibraryByAddress(const void *address); - static Libraries *instance() { return _instance; } + static Libraries *instance() { + static Libraries instance; + return &instance; + } + + // Delete copy constructor and assignment operator to prevent copies + Libraries(const Libraries&) = delete; + Libraries& operator=(const Libraries&) = delete; }; #endif // _LIBRARIES_H \ No newline at end of file diff --git a/ddprof-lib/src/main/cpp/livenessTracker.cpp b/ddprof-lib/src/main/cpp/livenessTracker.cpp index 289b9f521..9d465ad95 100644 --- a/ddprof-lib/src/main/cpp/livenessTracker.cpp +++ b/ddprof-lib/src/main/cpp/livenessTracker.cpp @@ -33,7 +33,6 @@ #include #include -LivenessTracker *const LivenessTracker::_instance = new LivenessTracker(); constexpr int LivenessTracker::MAX_TRACKING_TABLE_SIZE; constexpr int LivenessTracker::MIN_SAMPLING_INTERVAL; diff --git a/ddprof-lib/src/main/cpp/livenessTracker.h b/ddprof-lib/src/main/cpp/livenessTracker.h index 98bb0b2b8..101d8afae 100644 --- a/ddprof-lib/src/main/cpp/livenessTracker.h +++ b/ddprof-lib/src/main/cpp/livenessTracker.h @@ -82,10 +82,14 @@ class LivenessTracker { jlong getMaxMemory(JNIEnv *env); - static LivenessTracker *const _instance; - public: - static LivenessTracker *instance() { return _instance; } + static LivenessTracker *instance() { + static LivenessTracker instance; + return &instance; + } + // Delete copy constructor and assignment operator to prevent copies + LivenessTracker(const LivenessTracker&) = delete; + LivenessTracker& operator=(const LivenessTracker&) = delete; LivenessTracker() : _initialized(false), _enabled(false), _stored_error(Error::OK), From 08c2e28c5fa99ba1d70e350c1da58d944ac54103 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 12 Nov 2024 17:33:08 +0100 Subject: [PATCH 2/4] Add GHA aarch64 jobs --- .github/workflows/test_workflow.yml | 275 ++++++++++++++---- .../profiler/AbstractProfilerTest.java | 3 + .../profiler/cpu/VMStructsBasedCpuTest.java | 9 + 3 files changed, 233 insertions(+), 54 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index c54ef829e..9747a54cd 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -12,11 +12,11 @@ permissions: actions: read jobs: - test-linux-glibc: + test-linux-glibc-amd64: strategy: fail-fast: false matrix: - java_version: [ 8u412+9, 11.0.23+12, 17.0.11+12, 21.0.3+12, 22.0.1+12 ] + java_version: [ 8u432+7, 11.0.25+11, 17.0.13+12, 21.0.5+11, 23.0.1+13 ] config: ${{ fromJson(inputs.configuration) }} runs-on: ubuntu-latest timeout-minutes: 180 @@ -42,7 +42,7 @@ jobs: set +e export TEST_COMMIT=${{ github.sha }} - export TEST_CONFIGURATION=glibc/${{ matrix.java_version }} + export TEST_CONFIGURATION=glibc/${{ matrix.java_version }}-amd64 export LIBC=glibc export JAVA_TEST_HOME=$(pwd)/test_jdk export SANITIZER=${{ matrix.config }} @@ -56,17 +56,18 @@ jobs: printf "%s.%s.%s\n", v[1], v[2], v[3] } }') - ./gradlew :ddprof-test:test${{ matrix.config }} - if [ $? -ne 0 ]; then - echo "glibc-${{ matrix.java_version }}-${{ matrix.config }}" >> failures_glibc-${{ matrix.java_version }}-${{ matrix.config }}.txt + ./gradlew :ddprof-test:test${{ matrix.config }} + if [ $? -ne 0 ]; then + echo "glibc-${{ matrix.java_version }}-${{ matrix.config }}-amd64" >> failures_glibc-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt exit 1 fi - name: Upload logs uses: actions/upload-artifact@v3 if: always() with: - name: reports-linux-glibc-${{ matrix.java_version }}.zip + name: reports-linux-glibc-${{ matrix.java_version }}-amd64.zip path: | + /tmp/hs_err* ddprof-test/hs_err_* ddprof-test/build/reports/tests ddprof-lib/src/test/build/Testing/Temporary/LastTest.log @@ -74,21 +75,23 @@ jobs: - uses: actions/upload-artifact@v3 if: success() with: - name: x64-glibc-${{ matrix.java_version }}-${{ matrix.config }} + name: glibc-${{ matrix.java_version }}-${{ matrix.config }}-amd64 path: build/ - uses: actions/upload-artifact@v3 if: failure() with: name: failures - path: failures_glibc-${{ matrix.java_version }}-${{ matrix.config }}.txt + path: failures_glibc-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt - test-ubuntu-jdk: + test-linux-glibc-aarch64: strategy: fail-fast: false matrix: - java_version: [ '11.0.23-librca', '17.0.11-librca', '21.0.3-librca', '22.0.1-librca' ] + java_version: [ 8u432+7, 11.0.25+11, 17.0.13+12, 21.0.5+11, 23.0.1+13 ] config: ${{ fromJson(inputs.configuration) }} - runs-on: ubuntu-latest + runs-on: + group: ARM LINUX SHARED + labels: arm-4core-linux timeout-minutes: 180 steps: - uses: actions/checkout@v3 @@ -97,27 +100,87 @@ jobs: with: distribution: 'temurin' java-version: "11" - - name: Prepare OS + - name: Setup OS run: | - sudo apt-get update - sudo apt-get install -y curl zip unzip libgtest-dev libgmock-dev + sudo apt update -y + sudo apt remove -y g++ + sudo apt autoremove -y + sudo apt install -y curl zip unzip clang make build-essential - name: Prepare JDK ${{ matrix.java_version }} run: | - curl -s "https://get.sdkman.io" | bash - source "$HOME/.sdkman/bin/sdkman-init.sh" - echo 'n' | sdk install java ${{ matrix.java_version }} + wget -nv https://download.bell-sw.com/java/${{ matrix.java_version }}/bellsoft-jdk${{ matrix.java_version }}-linux-aarch64.tar.gz -O jdk.tar.gz + tar xzf *.tar.gz + find . -type d -name 'jdk*' -maxdepth 1| xargs -I {} mv {} test_jdk - name: Test run: | sudo sysctl vm.mmap_rnd_bits=28 - source "$HOME/.sdkman/bin/sdkman-init.sh" - + + set +e + export TEST_COMMIT=${{ github.sha }} + export TEST_CONFIGURATION=glibc/${{ matrix.java_version }}-aarch64 + export LIBC=glibc + export JAVA_TEST_HOME=$(pwd)/test_jdk + export SANITIZER=${{ matrix.config }} + ./gradlew :ddprof-test:test${{ matrix.config }} + if [ $? -ne 0 ]; then + echo "glibc-${{ matrix.java_version }}-${{ matrix.config }}-aarch64" >> failures_glibc-${{ matrix.java_version }}-${{ matrix.config }}-aarch64.txt + exit 1 + fi + - name: Upload logs + uses: actions/upload-artifact@v3 + if: always() + with: + name: reports-linux-glibc-${{ matrix.java_version }}-aarch64.zip + path: | + /tmp/hs_err* + ddprof-test/hs_err_* + ddprof-test/build/reports/tests + ddprof-lib/src/test/build/Testing/Temporary/LastTest.log + ddprof-lib/build/tmp/compileReleaseLinuxCpp/output.txt + - uses: actions/upload-artifact@v3 + if: success() + with: + name: glibc-${{ matrix.java_version }}-${{ matrix.config }}-aarch64 + path: build/ + - uses: actions/upload-artifact@v3 + if: failure() + with: + name: failures + path: failures_glibc-${{ matrix.java_version }}-${{ matrix.config }}-aarch64.txt + + test-linux-glibc-j9-amd64: + strategy: + fail-fast: false + matrix: + java_version: [ 8, 11, 17 ] + config: ${{ fromJson(inputs.configuration) }} + runs-on: ubuntu-latest + timeout-minutes: 180 + steps: + - uses: actions/checkout@v3 + - name: Setup OS + run: | + sudo apt-get update + sudo apt-get install -y curl zip unzip libgtest-dev libgmock-dev +# sudo sysctl vm.mmap_rnd_bits=28 + - name: Prepare test JDK + uses: actions/setup-java@v3 + with: + distribution: 'adopt-openj9' + java-version: "${{ matrix.java_version }}" + - name: Store JAVA_TEST_HOME + run: JAVA_PATH=$(which java) && echo "JAVA_TEST_HOME=${JAVA_PATH/\/bin\/java/\/}" >> $GITHUB_ENV + - name: Prepare build JDK + uses: actions/setup-java@v3 + with: + distribution: 'adopt-openj9' + java-version: "11" + - name: Test + run: | set +e export TEST_COMMIT=${{ github.sha }} export TEST_CONFIGURATION=glibc/${{ matrix.java_version }} export LIBC=glibc - export JAVA_TEST_HOME=${SDKMAN_DIR}/candidates/java/${{ matrix.java_version }} - export JAVA_HOME=$JAVA_HOME - export PATH=$JAVA_HOME/bin:$PATH export SANITIZER=${{ matrix.config }} export JAVA_VERSION=$(${JAVA_TEST_HOME}/bin/java -version 2>&1 | awk -F '"' '/version/ { split($2, v, "[._]"); @@ -129,47 +192,52 @@ jobs: printf "%s.%s.%s\n", v[1], v[2], v[3] } }') + chmod a+x gradlew ./gradlew :ddprof-test:test${{ matrix.config }} - if [ $? -ne 0 ]; then - echo "ubuntu-jdk-${{ matrix.java_version }}-${{ matrix.config }}" >> failures_ubuntu-jdk-${{ matrix.java_version }}-${{ matrix.config }}.txt + if [ $? -ne 0 ]; then + echo "glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-amd64" >> failures_glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt exit 1 fi - name: Upload logs uses: actions/upload-artifact@v3 if: always() with: - name: reports-linux-ubuntu-jdk-${{ matrix.java_version }}.zip + name: reports-linux-glibc-j9-${{ matrix.java_version }}-amd64.zip path: | - ddprof-test/hs_err_* + /tmp/javacore* + ddprof-test/javacore* ddprof-test/build/reports/tests ddprof-lib/src/test/build/Testing/Temporary/LastTest.log ddprof-lib/build/tmp/compileReleaseLinuxCpp/output.txt - uses: actions/upload-artifact@v3 if: success() with: - name: x64-ubuntu-jdk-${{ matrix.java_version }}-${{ matrix.config }} + name: glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-amd64 path: build/ - uses: actions/upload-artifact@v3 if: failure() with: name: failures - path: failures_ubuntu-jdk-${{ matrix.java_version }}-${{ matrix.config }}.txt + path: failures_glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt - test-linux-glibc-j9: + test-linux-glibc-j9-aarch64: strategy: fail-fast: false matrix: java_version: [ 8, 11, 17 ] config: ${{ fromJson(inputs.configuration) }} - runs-on: ubuntu-latest + runs-on: + group: ARM LINUX SHARED + labels: arm-4core-linux timeout-minutes: 180 steps: - uses: actions/checkout@v3 - name: Setup OS run: | - sudo apt-get update - sudo apt-get install -y curl zip unzip libgtest-dev libgmock-dev -# sudo sysctl vm.mmap_rnd_bits=28 + sudo apt update -y + sudo apt remove -y g++ + sudo apt autoremove -y + sudo apt install -y curl zip unzip clang make build-essential - name: Prepare test JDK uses: actions/setup-java@v3 with: @@ -201,16 +269,17 @@ jobs: }') chmod a+x gradlew ./gradlew :ddprof-test:test${{ matrix.config }} - if [ $? -ne 0 ]; then - echo "glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}" >> failures_glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}.txt + if [ $? -ne 0 ]; then + echo "glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-aarch64" >> failures_glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-aarch64.txt exit 1 fi - name: Upload logs uses: actions/upload-artifact@v3 if: always() with: - name: reports-linux-glibc-j9-${{ matrix.java_version }}.zip + name: reports-linux-glibc-j9-${{ matrix.java_version }}-aarch64.zip path: | + /tmp/javacore* ddprof-test/javacore* ddprof-test/build/reports/tests ddprof-lib/src/test/build/Testing/Temporary/LastTest.log @@ -218,13 +287,13 @@ jobs: - uses: actions/upload-artifact@v3 if: success() with: - name: x64-glibc-j9-${{ matrix.java_version }}-${{ matrix.config }} + name: glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-aarch64 path: build/ - uses: actions/upload-artifact@v3 if: failure() with: name: failures - path: failures_glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}.txt + path: failures_glibc-j9-${{ matrix.java_version }}-${{ matrix.config }}-aarch64.txt test-linux-glibc-oracle8: strategy: @@ -274,7 +343,7 @@ jobs: } }') ./gradlew :ddprof-test:test${{ matrix.config }} - if [ $? -ne 0 ]; then + if [ $? -ne 0 ]; then echo "glibc-oracle8-${{ matrix.config }}" >> failures_glibc-oracle8-${{ matrix.config }}.txt exit 1 fi @@ -299,11 +368,11 @@ jobs: name: failures path: failures_glibc-oracle8-${{ matrix.config }}.txt - test-linux-musl: + test-linux-musl-amd64: strategy: fail-fast: false matrix: - java_version: [ 8u412+9, 11.0.23+12, 17.0.11+12, 21.0.3+12, 22.0.1+12 ] + java_version: [ 8u432+7, 11.0.25+11, 17.0.13+12, 21.0.5+11, 23.0.1+13 ] config: ${{ fromJson(inputs.configuration) }} runs-on: ubuntu-latest timeout-minutes: 180 @@ -317,7 +386,7 @@ jobs: run: apk update && apk add curl moreutils wget hexdump linux-headers bash make g++ clang git cppcheck jq cmake gtest-dev gmock >/dev/null - name: Prepare build JDK run: | - wget -nv https://download.bell-sw.com/java/11.0.18+10/bellsoft-jdk11.0.18+10-linux-x64-musl.tar.gz -O jdk.tar.gz + wget -nv https://download.bell-sw.com/java/11.0.25+11/bellsoft-jdk11.0.25+11-linux-x64-musl.tar.gz -O jdk.tar.gz tar xzf *.tar.gz find . -type d -name 'jdk*' -maxdepth 1 | xargs -I {} mv {} build_jdk - name: Prepare JDK ${{ matrix.java_version }} @@ -346,16 +415,17 @@ jobs: } }') ./gradlew :ddprof-test:test${{ matrix.config }} - if [ $? -ne 0 ]; then - echo "musl-${{ matrix.java_version }}-${{ matrix.config }}" >> failures_musl-${{ matrix.java_version }}-${{ matrix.config }}.txt + if [ $? -ne 0 ]; then + echo "musl-${{ matrix.java_version }}-${{ matrix.config }}-amd64" >> failures_musl-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt exit 1 fi - name: Upload logs uses: actions/upload-artifact@v3 if: always() with: - name: reports-linux-musl-${{ matrix.java_version }}.zip + name: reports-linux-musl-${{ matrix.java_version }}-amd64.zip path: | + /tmp/hs_err* ddprof-test/hs_err_* ddprof-test/build/reports/tests ddprof-lib/src/test/build/Testing/Temporary/LastTest.log @@ -363,15 +433,15 @@ jobs: - uses: actions/upload-artifact@v3 if: success() with: - name: x64-musl-${{ matrix.java_version }}-${{ matrix.config }} + name: musl-${{ matrix.java_version }}-${{ matrix.config }}-amd64 path: build/ - uses: actions/upload-artifact@v3 if: failure() with: name: failures - path: failures_musl-${{ matrix.java_version }}-${{ matrix.config }}.txt + path: failures_musl-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt - test-linux-glibc-zing: + test-linux-glibc-zing-amd64: strategy: fail-fast: false matrix: @@ -441,15 +511,112 @@ jobs: } }') ./gradlew :ddprof-test:test${{ matrix.config }} - if [ $? -ne 0 ]; then - echo "glibc-zing-${{ matrix.java_version }}-${{ matrix.config }}" >> failures_zing-${{ matrix.java_version }}-${{ matrix.config }}.txt + if [ $? -ne 0 ]; then + echo "glibc-zing-${{ matrix.java_version }}-${{ matrix.config }}-amd64" >> failures_zing-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt + exit 1 + fi + - name: Upload logs + uses: actions/upload-artifact@v3 + if: always() + with: + name: reports-linux-zing-jdk-${{ matrix.java_version }}-amd64.zip + path: | + ddprof-test/hs_err_* + ddprof-test/build/reports/tests/test + ddprof-lib/src/test/build/Testing/Temporary/LastTest.log + ddprof-lib/build/tmp/compileReleaseLinuxCpp/output.txt + - uses: actions/upload-artifact@v3 + if: success() + with: + name: glibc-zing-${{ matrix.java_version }}-${{ matrix.config }}-amd64 + path: build/ + - uses: actions/upload-artifact@v3 + if: failure() + with: + name: failures + path: failures_zing-${{ matrix.java_version }}-${{ matrix.config }}-amd64.txt + + test-linux-glibc-zing-aarch64: + strategy: + fail-fast: false + matrix: + java_version: [ 8, 11, 17, 21 ] + config: ${{ fromJson(inputs.configuration) }} + runs-on: + group: ARM LINUX SHARED + labels: arm-4core-linux + timeout-minutes: 180 + + steps: + - name: Set config output + id: set_config + run: echo "::set-output name=config::${{ matrix.config }}" + - uses: actions/checkout@v3 + if: steps.set_config.outputs.config == 'release' || steps.set_config.outputs.config == 'debug' + - name: Setup OS + run: | + sudo apt update -y + sudo apt remove -y g++ + sudo apt autoremove -y + sudo apt install -y curl zip unzip clang make build-essential + - name: Prepare build JDK + if: steps.set_config.outputs.config == 'release' || steps.set_config.outputs.config == 'debug' + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: "11" + - name: Prepare JDK ${{ matrix.java_version }} + if: steps.set_config.outputs.config == 'release' || steps.set_config.outputs.config == 'debug' + run: | + sudo apt-get -y update && sudo apt-get -y install curl g++-9 gcc-9 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 100 --slave /usr/bin/g++ g++ /usr/bin/g++-9 + sudo update-alternatives --set gcc /usr/bin/gcc-9 + set -eux + sudo mkdir -p /usr/lib/jvm/zing + if [ "${{ matrix.java_version }}" = "8" ]; then + # jdk1.8.0_432 + curl -L --fail "https://cdn.azul.com/zing-zvm/ZVM24.10.0.0/zing24.10.0.0-4-jdk8.0.431-linux_aarch64.tar.gz" | sudo tar -xvzf - -C /usr/lib/jvm/zing --strip-components 1 + elif [ "${{ matrix.java_version }}" = "11" ]; then + # jdk 11.0.24 + curl -L --fail "https://cdn.azul.com/zing-zvm/ZVM24.10.0.0/zing24.10.0.0-4-jdk11.0.24.0.101-linux_aarch64.tar.gz" | sudo tar -xvzf - -C /usr/lib/jvm/zing --strip-components 1 + elif [ "${{ matrix.java_version }}" = "17" ]; then + # jdk 17.0.12 + curl -L --fail "https://cdn.azul.com/zing-zvm/ZVM24.10.0.0/zing24.10.0.0-4-jdk17.0.12.0.101-linux_aarch64.tar.gz" | sudo tar -xvzf - -C /usr/lib/jvm/zing --strip-components 1 + elif [ "${{ matrix.java_version }}" = "21" ]; then + # jdk 21.0.4 + curl -L --fail "https://cdn.azul.com/zing-zvm/ZVM24.10.0.0/zing24.10.0.0-4-jdk21.0.4.0.101-linux_aarch64.tar.gz" | sudo tar -xvzf - -C /usr/lib/jvm/zing --strip-components 1 + fi + - name: Test + if: steps.set_config.outputs.config == 'release' || steps.set_config.outputs.config == 'debug' + run: | + set +e + export TEST_COMMIT=${{ github.sha }} + export TEST_CONFIGURATION=glibc/${{ matrix.java_version }} + export LIBC=glibc + export JAVA_TEST_HOME=/usr/lib/jvm/zing + export JAVA_HOME=$JAVA_HOME + export PATH=$JAVA_HOME/bin:$PATH + export SANITIZER=${{ matrix.config }} + export JAVA_VERSION=$(${JAVA_TEST_HOME}/bin/java -version 2>&1 | awk -F '"' '/version/ { + split($2, v, "[._]"); + if (v[1] == "1") { + # Java 8 or older: Include major, minor, and update + printf "%s.%s.%s\n", v[2], v[3], v[4] + } else { + # Java 9 or newer: Major, minor, and patch + printf "%s.%s.%s\n", v[1], v[2], v[3] + } + }') + ./gradlew :ddprof-test:test${{ matrix.config }} + if [ $? -ne 0 ]; then + echo "glibc-zing-${{ matrix.java_version }}-${{ matrix.config }}-aarch64" >> failures_zing-${{ matrix.java_version }}-${{ matrix.config }}-aarch64.txt exit 1 fi - name: Upload logs uses: actions/upload-artifact@v3 if: always() with: - name: reports-linux-zing-jdk-${{ matrix.java_version }}.zip + name: reports-linux-zing-jdk-${{ matrix.java_version }}-aarch64.zip path: | ddprof-test/hs_err_* ddprof-test/build/reports/tests/test @@ -458,10 +625,10 @@ jobs: - uses: actions/upload-artifact@v3 if: success() with: - name: x64-glibc-zing-${{ matrix.java_version }}-${{ matrix.config }} + name: glibc-zing-${{ matrix.java_version }}-${{ matrix.config }}-aarch64 path: build/ - uses: actions/upload-artifact@v3 if: failure() with: name: failures - path: failures_zing-${{ matrix.java_version }}-${{ matrix.config }}.txt \ No newline at end of file + path: failures_zing-${{ matrix.java_version }}-${{ matrix.config }}-aarch64.txt \ No newline at end of file diff --git a/ddprof-test/src/test/java/com/datadoghq/profiler/AbstractProfilerTest.java b/ddprof-test/src/test/java/com/datadoghq/profiler/AbstractProfilerTest.java index f41ebe868..3a0219e35 100644 --- a/ddprof-test/src/test/java/com/datadoghq/profiler/AbstractProfilerTest.java +++ b/ddprof-test/src/test/java/com/datadoghq/profiler/AbstractProfilerTest.java @@ -142,9 +142,12 @@ protected boolean isPlatformSupported() { return true; } + protected void withTestAssumptions() {} + @BeforeEach public void setupProfiler() throws Exception { Assumptions.assumeTrue(isPlatformSupported()); + withTestAssumptions(); jfrDump = Files.createTempFile(Paths.get("/tmp"), getClass().getName() + UUID.randomUUID(), ".jfr"); profiler = JavaProfiler.getInstance(); diff --git a/ddprof-test/src/test/java/com/datadoghq/profiler/cpu/VMStructsBasedCpuTest.java b/ddprof-test/src/test/java/com/datadoghq/profiler/cpu/VMStructsBasedCpuTest.java index 4ec215516..991e4ae7a 100644 --- a/ddprof-test/src/test/java/com/datadoghq/profiler/cpu/VMStructsBasedCpuTest.java +++ b/ddprof-test/src/test/java/com/datadoghq/profiler/cpu/VMStructsBasedCpuTest.java @@ -2,6 +2,7 @@ import com.datadoghq.profiler.AbstractProfilerTest; import com.datadoghq.profiler.Platform; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.openjdk.jmc.common.item.IItem; import org.openjdk.jmc.common.item.IItemCollection; @@ -18,8 +19,16 @@ public class VMStructsBasedCpuTest extends AbstractProfilerTest { private ProfiledCode profiledCode; + @Override + protected void withTestAssumptions() { + // vmstructs based stackwalking will throw ISE on Java 23 + Assumptions.assumeFalse(Platform.isJavaVersionAtLeast(23)); + } + @Override protected void before() { + // vmstructs based stackwalking will throw ISE on Java 23 + Assumptions.assumeFalse(Platform.isJavaVersionAtLeast(23)); profiledCode = new ProfiledCode(profiler); } From 729d9f9653c59cecb50948bb6f1d143d3360d904 Mon Sep 17 00:00:00 2001 From: Andrei Pangin Date: Tue, 16 Jan 2024 23:49:01 +0000 Subject: [PATCH 3/4] #819: Extend AArch64 stack walking fix to cstack=dwarf --- ddprof-lib/src/main/cpp/stackFrame.h | 2 +- ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp | 3 +-- ddprof-lib/src/main/cpp/stackFrame_arm.cpp | 2 +- ddprof-lib/src/main/cpp/stackFrame_i386.cpp | 2 +- ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp | 2 +- ddprof-lib/src/main/cpp/stackFrame_x64.cpp | 2 +- ddprof-lib/src/main/cpp/stackWalker.cpp | 4 +++- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ddprof-lib/src/main/cpp/stackFrame.h b/ddprof-lib/src/main/cpp/stackFrame.h index 262c0a3af..6eee5e95a 100644 --- a/ddprof-lib/src/main/cpp/stackFrame.h +++ b/ddprof-lib/src/main/cpp/stackFrame.h @@ -75,7 +75,7 @@ class StackFrame { uintptr_t &sp, uintptr_t &fp); bool unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, uintptr_t &fp); - void adjustCompiled(NMethod *nm, const void *pc, uintptr_t &sp); + void adjustSP(const void *entry, const void *pc, uintptr_t &sp); bool skipFaultInstruction(); diff --git a/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp b/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp index 3df6a6e05..338fae500 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp @@ -136,9 +136,8 @@ bool StackFrame::unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, return true; } -void StackFrame::adjustCompiled(NMethod *nm, const void *pc, uintptr_t &sp) { +void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { instruction_t *ip = (instruction_t *)pc; - instruction_t *entry = (instruction_t *)nm->entry(); if (ip > entry && (ip[-1] == 0xa9bf27ff || (ip[-1] == 0xd63f0100 && ip[-2] == 0xa9bf27ff))) { // When calling a leaf native from Java, JVM puts a dummy frame link onto diff --git a/ddprof-lib/src/main/cpp/stackFrame_arm.cpp b/ddprof-lib/src/main/cpp/stackFrame_arm.cpp index b3ab2c8ab..1c2ab8801 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_arm.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_arm.cpp @@ -108,7 +108,7 @@ bool StackFrame::unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, return true; } -void StackFrame::adjustCompiled(NMethod *nm, const void *pc, uintptr_t &sp) { +void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } diff --git a/ddprof-lib/src/main/cpp/stackFrame_i386.cpp b/ddprof-lib/src/main/cpp/stackFrame_i386.cpp index 90630eb2d..2146081c6 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_i386.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_i386.cpp @@ -115,7 +115,7 @@ bool StackFrame::unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, return false; } -void StackFrame::adjustCompiled(NMethod *nm, const void *pc, uintptr_t &sp) { +void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } diff --git a/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp b/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp index 66af0638b..a95803b3f 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp @@ -143,7 +143,7 @@ bool StackFrame::unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, return true; } -void StackFrame::adjustCompiled(NMethod *nm, const void *pc, uintptr_t &sp) { +void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } diff --git a/ddprof-lib/src/main/cpp/stackFrame_x64.cpp b/ddprof-lib/src/main/cpp/stackFrame_x64.cpp index 762ab33f5..0507eac8c 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_x64.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_x64.cpp @@ -141,7 +141,7 @@ bool StackFrame::unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, return false; } -void StackFrame::adjustCompiled(NMethod *nm, const void *pc, uintptr_t &sp) { +void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } diff --git a/ddprof-lib/src/main/cpp/stackWalker.cpp b/ddprof-lib/src/main/cpp/stackWalker.cpp index 5907cf902..c75cfdc0a 100644 --- a/ddprof-lib/src/main/cpp/stackWalker.cpp +++ b/ddprof-lib/src/main/cpp/stackWalker.cpp @@ -155,6 +155,8 @@ int StackWalker::walkDwarf(void *ucontext, const void **callchain, break; } if (CodeHeap::contains(pc)) { + const void* page_start = (const void*)((uintptr_t)pc & ~0xfffUL); + frame.adjustSP(page_start, pc, sp); java_ctx->set(pc, sp, fp); break; } @@ -302,7 +304,7 @@ int StackWalker::walkVM(void *ucontext, ASGCT_CallFrame *frames, int max_depth, // Handle situations when sp is temporarily changed in the compiled // code - frame.adjustCompiled(nm, pc, sp); + frame.adjustSP(nm->entry(), pc, sp); sp += nm->frameSize() * sizeof(void *); fp = ((uintptr_t *)sp)[-FRAME_PC_SLOT - 1]; From dcc8730d416ee3f33afd4c379cbd16c7eaff0939 Mon Sep 17 00:00:00 2001 From: Andrei Pangin Date: Sun, 10 Mar 2024 22:07:04 +0000 Subject: [PATCH 4/4] #893: Fix [no_Java_frame] on ARM64 --- ddprof-lib/src/main/cpp/stackFrame.h | 1 + ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp | 13 +++++++++++++ ddprof-lib/src/main/cpp/stackFrame_arm.cpp | 5 +++++ ddprof-lib/src/main/cpp/stackFrame_i386.cpp | 5 +++++ ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp | 5 +++++ ddprof-lib/src/main/cpp/stackFrame_x64.cpp | 5 +++++ ddprof-lib/src/main/cpp/stackWalker.cpp | 5 +++-- 7 files changed, 37 insertions(+), 2 deletions(-) diff --git a/ddprof-lib/src/main/cpp/stackFrame.h b/ddprof-lib/src/main/cpp/stackFrame.h index 6eee5e95a..857e38f60 100644 --- a/ddprof-lib/src/main/cpp/stackFrame.h +++ b/ddprof-lib/src/main/cpp/stackFrame.h @@ -74,6 +74,7 @@ class StackFrame { bool unwindStub(instruction_t *entry, const char *name, uintptr_t &pc, uintptr_t &sp, uintptr_t &fp); bool unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, uintptr_t &fp); + bool unwindAtomicStub(const void*& pc); void adjustSP(const void *entry, const void *pc, uintptr_t &sp); diff --git a/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp b/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp index 338fae500..d9af9a6b3 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_aarch64.cpp @@ -136,6 +136,19 @@ bool StackFrame::unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp, return true; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // VM threads may call generated atomic stubs, which are not normally walkable + const void* lr = (const void*)link(); + if (VMStructs::libjvm()->contains(lr)) { + NMethod* nm = CodeHeap::findNMethod(pc); + if (nm != NULL && strncmp(nm->name(), "Stub", 4) == 0) { + pc = lr; + return true; + } + } + return false; +} + void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { instruction_t *ip = (instruction_t *)pc; if (ip > entry && (ip[-1] == 0xa9bf27ff || diff --git a/ddprof-lib/src/main/cpp/stackFrame_arm.cpp b/ddprof-lib/src/main/cpp/stackFrame_arm.cpp index 1c2ab8801..5f72491eb 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_arm.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_arm.cpp @@ -112,6 +112,11 @@ void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + bool StackFrame::skipFaultInstruction() { return false; } bool StackFrame::checkInterruptedSyscall() { diff --git a/ddprof-lib/src/main/cpp/stackFrame_i386.cpp b/ddprof-lib/src/main/cpp/stackFrame_i386.cpp index 2146081c6..fdf4159a6 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_i386.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_i386.cpp @@ -119,6 +119,11 @@ void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + bool StackFrame::skipFaultInstruction() { return false; } bool StackFrame::checkInterruptedSyscall() { diff --git a/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp b/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp index a95803b3f..a06c0c0e1 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_ppc64.cpp @@ -147,6 +147,11 @@ void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + bool StackFrame::skipFaultInstruction() { return false; } bool StackFrame::checkInterruptedSyscall() { diff --git a/ddprof-lib/src/main/cpp/stackFrame_x64.cpp b/ddprof-lib/src/main/cpp/stackFrame_x64.cpp index 0507eac8c..40fcb8cfa 100644 --- a/ddprof-lib/src/main/cpp/stackFrame_x64.cpp +++ b/ddprof-lib/src/main/cpp/stackFrame_x64.cpp @@ -145,6 +145,11 @@ void StackFrame::adjustSP(const void *entry, const void *pc, uintptr_t &sp) { // Not needed } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + // Skip failed MOV instruction by writing 0 to destination register bool StackFrame::skipFaultInstruction() { unsigned int insn = *(unsigned int *)pc(); diff --git a/ddprof-lib/src/main/cpp/stackWalker.cpp b/ddprof-lib/src/main/cpp/stackWalker.cpp index c75cfdc0a..6df11e922 100644 --- a/ddprof-lib/src/main/cpp/stackWalker.cpp +++ b/ddprof-lib/src/main/cpp/stackWalker.cpp @@ -71,6 +71,7 @@ int StackWalker::walkFP(void *ucontext, const void **callchain, int max_depth, uintptr_t sp; uintptr_t bottom = (uintptr_t)&sp + MAX_WALK_SIZE; + StackFrame frame(ucontext); if (ucontext == NULL) { pc = __builtin_return_address(0); fp = (uintptr_t)__builtin_frame_address(1); @@ -92,7 +93,7 @@ int StackWalker::walkFP(void *ucontext, const void **callchain, int max_depth, *truncated = true; break; } - if (CodeHeap::contains(pc)) { + if (CodeHeap::contains(pc) && !(depth == 0 && frame.unwindAtomicStub(pc))) { java_ctx->set(pc, sp, fp); break; } @@ -154,7 +155,7 @@ int StackWalker::walkDwarf(void *ucontext, const void **callchain, *truncated = true; break; } - if (CodeHeap::contains(pc)) { + if (CodeHeap::contains(pc) && !(depth == 0 && frame.unwindAtomicStub(pc))) { const void* page_start = (const void*)((uintptr_t)pc & ~0xfffUL); frame.adjustSP(page_start, pc, sp); java_ctx->set(pc, sp, fp);