Skip to content

Commit 743c821

Browse files
author
Evgeny Astigeevich
committed
8362193: Re-work MacOS/AArch64 SpinPause to handle SB
Reviewed-by: shade, aph
1 parent b02c125 commit 743c821

File tree

10 files changed

+192
-52
lines changed

10 files changed

+192
-52
lines changed

src/hotspot/cpu/aarch64/globals_aarch64.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ define_pd_global(intx, InlineSmallCode, 1000);
117117
product(ccstr, OnSpinWaitInst, "yield", DIAGNOSTIC, \
118118
"The instruction to use to implement " \
119119
"java.lang.Thread.onSpinWait()." \
120-
"Options: none, nop, isb, yield, sb.") \
120+
"Valid values are: none, nop, isb, yield, sb.") \
121+
constraint(OnSpinWaitInstNameConstraintFunc, AtParse) \
121122
product(uint, OnSpinWaitInstCount, 1, DIAGNOSTIC, \
122123
"The number of OnSpinWaitInst instructions to generate." \
123124
"It cannot be used with OnSpinWaitInst=none.") \

src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6816,6 +6816,7 @@ void MacroAssembler::spin_wait() {
68166816
yield();
68176817
break;
68186818
case SpinWait::SB:
6819+
assert(VM_Version::supports_sb(), "current CPU does not support SB instruction");
68196820
sb();
68206821
break;
68216822
default:
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
#include "spin_wait_aarch64.hpp"
25+
#include "utilities/debug.hpp"
26+
27+
#include <string.h>
28+
29+
bool SpinWait::supports(const char *name) {
30+
return name != nullptr &&
31+
(strcmp(name, "nop") == 0 ||
32+
strcmp(name, "isb") == 0 ||
33+
strcmp(name, "yield") == 0 ||
34+
strcmp(name, "sb") == 0 ||
35+
strcmp(name, "none") == 0);
36+
}
37+
38+
SpinWait::Inst SpinWait::from_name(const char* name) {
39+
assert(supports(name), "checked by OnSpinWaitInstNameConstraintFunc");
40+
41+
if (strcmp(name, "nop") == 0) {
42+
return SpinWait::NOP;
43+
} else if (strcmp(name, "isb") == 0) {
44+
return SpinWait::ISB;
45+
} else if (strcmp(name, "yield") == 0) {
46+
return SpinWait::YIELD;
47+
} else if (strcmp(name, "sb") == 0) {
48+
return SpinWait::SB;
49+
}
50+
51+
return SpinWait::NONE;
52+
}

src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2020
* or visit www.oracle.com if you need additional information or have any
2121
* questions.
22-
*
2322
*/
2423

2524
#ifndef CPU_AARCH64_SPIN_WAIT_AARCH64_HPP
@@ -39,11 +38,16 @@ class SpinWait {
3938
Inst _inst;
4039
int _count;
4140

41+
Inst from_name(const char *name);
42+
4243
public:
43-
SpinWait(Inst inst = NONE, int count = 0) : _inst(inst), _count(count) {}
44+
SpinWait(Inst inst = NONE, int count = 0) : _inst(inst), _count(inst == NONE ? 0 : count) {}
45+
SpinWait(const char *name, int count) : SpinWait(from_name(name), count) {}
4446

4547
Inst inst() const { return _inst; }
4648
int inst_count() const { return _count; }
49+
50+
static bool supports(const char *name);
4751
};
4852

4953
#endif // CPU_AARCH64_SPIN_WAIT_AARCH64_HPP

src/hotspot/cpu/aarch64/vm_version_aarch64.cpp

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,12 @@ uintptr_t VM_Version::_pac_mask;
5151
SpinWait VM_Version::_spin_wait;
5252

5353
static SpinWait get_spin_wait_desc() {
54-
if (strcmp(OnSpinWaitInst, "nop") == 0) {
55-
return SpinWait(SpinWait::NOP, OnSpinWaitInstCount);
56-
} else if (strcmp(OnSpinWaitInst, "isb") == 0) {
57-
return SpinWait(SpinWait::ISB, OnSpinWaitInstCount);
58-
} else if (strcmp(OnSpinWaitInst, "yield") == 0) {
59-
return SpinWait(SpinWait::YIELD, OnSpinWaitInstCount);
60-
} else if (strcmp(OnSpinWaitInst, "sb") == 0) {
61-
if (!VM_Version::supports_sb()) {
62-
vm_exit_during_initialization("OnSpinWaitInst is SB but current CPU does not support SB instruction");
63-
}
64-
return SpinWait(SpinWait::SB, OnSpinWaitInstCount);
65-
} else if (strcmp(OnSpinWaitInst, "none") != 0) {
66-
vm_exit_during_initialization("The options for OnSpinWaitInst are nop, isb, yield, sb, and none", OnSpinWaitInst);
67-
}
68-
69-
if (!FLAG_IS_DEFAULT(OnSpinWaitInstCount) && OnSpinWaitInstCount > 0) {
70-
vm_exit_during_initialization("OnSpinWaitInstCount cannot be used for OnSpinWaitInst 'none'");
54+
SpinWait spin_wait(OnSpinWaitInst, OnSpinWaitInstCount);
55+
if (spin_wait.inst() == SpinWait::SB && !VM_Version::supports_sb()) {
56+
vm_exit_during_initialization("OnSpinWaitInst is SB but current CPU does not support SB instruction");
7157
}
7258

73-
return SpinWait{};
59+
return spin_wait;
7460
}
7561

7662
void VM_Version::initialize() {

src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@
4949
#include "runtime/sharedRuntime.hpp"
5050
#include "runtime/stubRoutines.hpp"
5151
#include "runtime/timer.hpp"
52+
#include "runtime/vm_version.hpp"
5253
#include "signals_posix.hpp"
5354
#include "utilities/align.hpp"
55+
#include "utilities/debug.hpp"
5456
#include "utilities/events.hpp"
5557
#include "utilities/vmError.hpp"
5658

@@ -524,40 +526,32 @@ static inline void atomic_copy64(const volatile void *src, volatile void *dst) {
524526
}
525527

526528
extern "C" {
527-
// needs local assembler label '1:' to avoid trouble when using linktime optimization
528529
int SpinPause() {
529530
// We don't use StubRoutines::aarch64::spin_wait stub in order to
530531
// avoid a costly call to os::current_thread_enable_wx() on MacOS.
531532
// We should return 1 if SpinPause is implemented, and since there
532-
// will be a sequence of 11 instructions for NONE and YIELD and 12
533-
// instructions for NOP and ISB, SpinPause will always return 1.
534-
uint64_t br_dst;
535-
const int instructions_per_case = 2;
536-
int64_t off = VM_Version::spin_wait_desc().inst() * instructions_per_case * Assembler::instruction_size;
537-
538-
assert(VM_Version::spin_wait_desc().inst() >= SpinWait::NONE &&
539-
VM_Version::spin_wait_desc().inst() <= SpinWait::YIELD, "must be");
540-
assert(-1 == SpinWait::NONE, "must be");
541-
assert( 0 == SpinWait::NOP, "must be");
542-
assert( 1 == SpinWait::ISB, "must be");
543-
assert( 2 == SpinWait::YIELD, "must be");
544-
545-
asm volatile(
546-
" adr %[d], 20 \n" // 20 == PC here + 5 instructions => address
547-
// to entry for case SpinWait::NOP
548-
" add %[d], %[d], %[o] \n"
549-
" br %[d] \n"
550-
" b 1f \n" // case SpinWait::NONE (-1)
551-
" nop \n" // padding
552-
" nop \n" // case SpinWait::NOP ( 0)
553-
" b 1f \n"
554-
" isb \n" // case SpinWait::ISB ( 1)
555-
" b 1f \n"
556-
" yield \n" // case SpinWait::YIELD ( 2)
557-
"1: \n"
558-
: [d]"=&r"(br_dst)
559-
: [o]"r"(off)
560-
: "memory");
533+
// will be always a sequence of instructions, SpinPause will always return 1.
534+
switch (VM_Version::spin_wait_desc().inst()) {
535+
case SpinWait::NONE:
536+
break;
537+
case SpinWait::NOP:
538+
asm volatile("nop" : : : "memory");
539+
break;
540+
case SpinWait::ISB:
541+
asm volatile("isb" : : : "memory");
542+
break;
543+
case SpinWait::YIELD:
544+
asm volatile("yield" : : : "memory");
545+
break;
546+
case SpinWait::SB:
547+
assert(VM_Version::supports_sb(), "current CPU does not support SB instruction");
548+
asm volatile(".inst 0xd50330ff" : : : "memory");
549+
break;
550+
#ifdef ASSERT
551+
default:
552+
ShouldNotReachHere();
553+
#endif
554+
}
561555
return 1;
562556
}
563557

src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,25 @@ JVMFlag::Error NUMAInterleaveGranularityConstraintFunc(size_t value, bool verbos
127127

128128
return JVMFlag::SUCCESS;
129129
}
130+
131+
JVMFlag::Error OnSpinWaitInstNameConstraintFunc(ccstr value, bool verbose) {
132+
#ifdef AARCH64
133+
if (value == nullptr) {
134+
JVMFlag::printError(verbose, "OnSpinWaitInst cannot be empty\n");
135+
return JVMFlag::VIOLATES_CONSTRAINT;
136+
}
137+
138+
if (strcmp(value, "nop") != 0 &&
139+
strcmp(value, "isb") != 0 &&
140+
strcmp(value, "yield") != 0 &&
141+
strcmp(value, "sb") != 0 &&
142+
strcmp(value, "none") != 0) {
143+
JVMFlag::printError(verbose,
144+
"Unrecognized value %s for OnSpinWaitInst. Must be one of the following: "
145+
"nop, isb, yield, sb, none\n",
146+
value);
147+
return JVMFlag::VIOLATES_CONSTRAINT;
148+
}
149+
#endif
150+
return JVMFlag::SUCCESS;
151+
}

src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
f(int, ObjectAlignmentInBytesConstraintFunc) \
4141
f(int, ContendedPaddingWidthConstraintFunc) \
4242
f(size_t, VMPageSizeConstraintFunc) \
43-
f(size_t, NUMAInterleaveGranularityConstraintFunc)
43+
f(size_t, NUMAInterleaveGranularityConstraintFunc) \
44+
f(ccstr, OnSpinWaitInstNameConstraintFunc)
4445

4546
RUNTIME_CONSTRAINTS(DECLARE_CONSTRAINT)
4647

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
#if defined(AARCH64) && !defined(ZERO)
25+
26+
#include "utilities/spinYield.hpp"
27+
#include "unittest.hpp"
28+
29+
TEST_VM(SpinPause, sanity) {
30+
ASSERT_EQ(SpinPause(), 1);
31+
}
32+
33+
#endif // AARCH64
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 id=default_armv8_0
26+
* @bug 8362193
27+
* @summary Run SpinPause gtest using different instructions for SpinPause
28+
* @library /test/lib
29+
* @requires vm.flagless
30+
* @requires os.arch=="aarch64"
31+
* @run main/native GTestWrapper --gtest_filter=SpinPause*
32+
* @run main/native GTestWrapper --gtest_filter=SpinPause* -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none
33+
* @run main/native GTestWrapper --gtest_filter=SpinPause* -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop
34+
* @run main/native GTestWrapper --gtest_filter=SpinPause* -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb
35+
* @run main/native GTestWrapper --gtest_filter=SpinPause* -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield
36+
*/
37+
38+
/*
39+
* @test id=sb_armv8_5
40+
* @bug 8362193
41+
* @summary Run SpinPause gtest using SB instruction for SpinPause
42+
* @library /test/lib
43+
* @requires vm.flagless
44+
* @requires (os.arch=="aarch64" & vm.cpu.features ~= ".*sb.*")
45+
* @run main/native GTestWrapper --gtest_filter=SpinPause* -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=sb
46+
*/

0 commit comments

Comments
 (0)