Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8278241: Implement JVM SpinPause on linux-aarch64
Reviewed-by: aph, phh
  • Loading branch information
eastig authored and Paul Hohensee committed Dec 15, 2021
1 parent fcebe65 commit bcb79fd
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 1 deletion.
14 changes: 14 additions & 0 deletions src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
Expand Up @@ -6397,6 +6397,18 @@ class StubGenerator: public StubCodeGenerator {
return start;
}

// Support for spin waits.
address generate_spin_wait() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "spin_wait");
address start = __ pc();

__ spin_wait();
__ ret(lr);

return start;
}

#ifdef LINUX

// ARMv8.1 LSE versions of the atomic stubs used by Atomic::PlatformXX.
Expand Down Expand Up @@ -7715,6 +7727,8 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
}

StubRoutines::aarch64::_spin_wait = generate_spin_wait();

#ifdef LINUX

generate_atomic_entry_points();
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp
Expand Up @@ -57,6 +57,10 @@ address StubRoutines::aarch64::_string_indexof_linear_uu = NULL;
address StubRoutines::aarch64::_string_indexof_linear_ul = NULL;
address StubRoutines::aarch64::_large_byte_array_inflate = NULL;
address StubRoutines::aarch64::_method_entry_barrier = NULL;

static void empty_spin_wait() { }
address StubRoutines::aarch64::_spin_wait = CAST_FROM_FN_PTR(address, empty_spin_wait);

bool StubRoutines::aarch64::_completed = false;

/**
Expand Down
6 changes: 6 additions & 0 deletions src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp
Expand Up @@ -72,6 +72,8 @@ class aarch64 {

static address _method_entry_barrier;

static address _spin_wait;

static bool _completed;

public:
Expand Down Expand Up @@ -177,6 +179,10 @@ class aarch64 {
return _method_entry_barrier;
}

static address spin_wait() {
return _spin_wait;
}

static bool complete() {
return _completed;
}
Expand Down
15 changes: 14 additions & 1 deletion src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
Expand Up @@ -382,7 +382,20 @@ int os::extra_bang_size_in_bytes() {

extern "C" {
int SpinPause() {
return 0;
using spin_wait_func_ptr_t = void (*)();
spin_wait_func_ptr_t func = CAST_TO_FN_PTR(spin_wait_func_ptr_t, StubRoutines::aarch64::spin_wait());
assert(func != nullptr, "StubRoutines::aarch64::spin_wait must not be null.");
(*func)();
// If StubRoutines::aarch64::spin_wait consists of only a RET,
// SpinPause can be considered as implemented. There will be a sequence
// of instructions for:
// - call of SpinPause
// - load of StubRoutines::aarch64::spin_wait stub pointer
// - indirect call of the stub
// - return from the stub
// - return from SpinPause
// So '1' always is returned.
return 1;
}

void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
Expand Down
87 changes: 87 additions & 0 deletions test/hotspot/jtreg/runtime/Thread/TestSpinPause.java
@@ -0,0 +1,87 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/**
* @test TestSpinPause
* @summary JVM runtime can use SpinPause function for synchronized statements.
* Check different implementations of JVM SpinPause don't crash JVM.
* @bug 8278241
* @library /test/lib
*
* @requires os.arch=="aarch64"
*
* @run main/othervm TestSpinPause
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause
* @run main/othervm -Xint TestSpinPause
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause
* @run main/othervm -Xcomp TestSpinPause
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause
*/

public class TestSpinPause {
private Integer[] valueHolder;

private TestSpinPause () {
valueHolder = new Integer[] {Integer.valueOf(101)};
}

private void getSet() {
final int iterCount = 100;
for (int i = 0; i < iterCount; ++i) {
synchronized (valueHolder) {
Integer v = valueHolder[0];
valueHolder[0] = Integer.reverse(v);
}
}
}

public static void main(String[] args) throws Exception {
TestSpinPause test = new TestSpinPause();
Thread t1 = new Thread(test::getSet);
Thread t2 = new Thread(test::getSet);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Done: " + test.valueHolder[0]);
}
}

1 comment on commit bcb79fd

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.