Skip to content

Commit bcb79fd

Browse files
eastigPaul Hohensee
authored andcommitted
8278241: Implement JVM SpinPause on linux-aarch64
Reviewed-by: aph, phh
1 parent fcebe65 commit bcb79fd

File tree

5 files changed

+125
-1
lines changed

5 files changed

+125
-1
lines changed

src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6397,6 +6397,18 @@ class StubGenerator: public StubCodeGenerator {
63976397
return start;
63986398
}
63996399

6400+
// Support for spin waits.
6401+
address generate_spin_wait() {
6402+
__ align(CodeEntryAlignment);
6403+
StubCodeMark mark(this, "StubRoutines", "spin_wait");
6404+
address start = __ pc();
6405+
6406+
__ spin_wait();
6407+
__ ret(lr);
6408+
6409+
return start;
6410+
}
6411+
64006412
#ifdef LINUX
64016413

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

7730+
StubRoutines::aarch64::_spin_wait = generate_spin_wait();
7731+
77187732
#ifdef LINUX
77197733

77207734
generate_atomic_entry_points();

src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ address StubRoutines::aarch64::_string_indexof_linear_uu = NULL;
5757
address StubRoutines::aarch64::_string_indexof_linear_ul = NULL;
5858
address StubRoutines::aarch64::_large_byte_array_inflate = NULL;
5959
address StubRoutines::aarch64::_method_entry_barrier = NULL;
60+
61+
static void empty_spin_wait() { }
62+
address StubRoutines::aarch64::_spin_wait = CAST_FROM_FN_PTR(address, empty_spin_wait);
63+
6064
bool StubRoutines::aarch64::_completed = false;
6165

6266
/**

src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class aarch64 {
7272

7373
static address _method_entry_barrier;
7474

75+
static address _spin_wait;
76+
7577
static bool _completed;
7678

7779
public:
@@ -177,6 +179,10 @@ class aarch64 {
177179
return _method_entry_barrier;
178180
}
179181

182+
static address spin_wait() {
183+
return _spin_wait;
184+
}
185+
180186
static bool complete() {
181187
return _completed;
182188
}

src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,20 @@ int os::extra_bang_size_in_bytes() {
382382

383383
extern "C" {
384384
int SpinPause() {
385-
return 0;
385+
using spin_wait_func_ptr_t = void (*)();
386+
spin_wait_func_ptr_t func = CAST_TO_FN_PTR(spin_wait_func_ptr_t, StubRoutines::aarch64::spin_wait());
387+
assert(func != nullptr, "StubRoutines::aarch64::spin_wait must not be null.");
388+
(*func)();
389+
// If StubRoutines::aarch64::spin_wait consists of only a RET,
390+
// SpinPause can be considered as implemented. There will be a sequence
391+
// of instructions for:
392+
// - call of SpinPause
393+
// - load of StubRoutines::aarch64::spin_wait stub pointer
394+
// - indirect call of the stub
395+
// - return from the stub
396+
// - return from SpinPause
397+
// So '1' always is returned.
398+
return 1;
386399
}
387400

388401
void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright Amazon.com Inc. or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/**
25+
* @test TestSpinPause
26+
* @summary JVM runtime can use SpinPause function for synchronized statements.
27+
* Check different implementations of JVM SpinPause don't crash JVM.
28+
* @bug 8278241
29+
* @library /test/lib
30+
*
31+
* @requires os.arch=="aarch64"
32+
*
33+
* @run main/othervm TestSpinPause
34+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause
35+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause
36+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause
37+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause
38+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause
39+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause
40+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause
41+
* @run main/othervm -Xint TestSpinPause
42+
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause
43+
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause
44+
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause
45+
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause
46+
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause
47+
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause
48+
* @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause
49+
* @run main/othervm -Xcomp TestSpinPause
50+
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause
51+
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause
52+
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause
53+
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause
54+
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause
55+
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause
56+
* @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause
57+
*/
58+
59+
public class TestSpinPause {
60+
private Integer[] valueHolder;
61+
62+
private TestSpinPause () {
63+
valueHolder = new Integer[] {Integer.valueOf(101)};
64+
}
65+
66+
private void getSet() {
67+
final int iterCount = 100;
68+
for (int i = 0; i < iterCount; ++i) {
69+
synchronized (valueHolder) {
70+
Integer v = valueHolder[0];
71+
valueHolder[0] = Integer.reverse(v);
72+
}
73+
}
74+
}
75+
76+
public static void main(String[] args) throws Exception {
77+
TestSpinPause test = new TestSpinPause();
78+
Thread t1 = new Thread(test::getSet);
79+
Thread t2 = new Thread(test::getSet);
80+
t1.start();
81+
t2.start();
82+
t1.join();
83+
t2.join();
84+
System.out.println("Done: " + test.valueHolder[0]);
85+
}
86+
}
87+

0 commit comments

Comments
 (0)