8194258: PPC64 safepoint mechanism: Fix initialization on AIX and support SIGTRAP
Use mmap on AIX to allocate protected page. Use trap instructions for polling if UseSIGTRAP is enabled. Reviewed-by: rehn, goetz
This commit is contained in:
parent
15ef7c04a2
commit
201a232a23
src/hotspot
cpu/ppc
os/aix
os_cpu
share/runtime
test/hotspot/jtreg/runtime/logging
@ -55,5 +55,9 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
|
||||
#define SUPPORT_RESERVED_STACK_AREA
|
||||
|
||||
#define THREAD_LOCAL_POLL
|
||||
// If UseSIGTRAP is active, we only use the poll bit and no polling page.
|
||||
// Otherwise, we fall back to usage of the polling page in nmethods.
|
||||
// Define the condition to use this -XX flag.
|
||||
#define USE_POLL_BIT_ONLY UseSIGTRAP
|
||||
|
||||
#endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "asm/macroAssembler.hpp"
|
||||
#include "asm/codeBuffer.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "runtime/safepointMechanism.hpp"
|
||||
|
||||
inline bool MacroAssembler::is_ld_largeoffset(address a) {
|
||||
const int inst1 = *(int *)a;
|
||||
@ -261,7 +262,12 @@ inline address MacroAssembler::last_calls_return_pc() {
|
||||
|
||||
// Read from the polling page, its address is already in a register.
|
||||
inline void MacroAssembler::load_from_polling_page(Register polling_page_address, int offset) {
|
||||
ld(R0, offset, polling_page_address);
|
||||
if (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) {
|
||||
int encoding = SafepointMechanism::poll_bit();
|
||||
tdi(traptoGreaterThanUnsigned | traptoEqual, polling_page_address, encoding);
|
||||
} else {
|
||||
ld(R0, offset, polling_page_address);
|
||||
}
|
||||
}
|
||||
|
||||
// Trap-instruction-based checks.
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/icache.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/safepointMechanism.hpp"
|
||||
|
||||
// We have interfaces for the following instructions:
|
||||
//
|
||||
@ -93,6 +94,11 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
|
||||
bool is_safepoint_poll() {
|
||||
// Is the current instruction a POTENTIAL read access to the polling page?
|
||||
// The current arguments of the instruction are not checked!
|
||||
if (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) {
|
||||
int encoding = SafepointMechanism::poll_bit();
|
||||
return MacroAssembler::is_tdi(long_at(0), Assembler::traptoGreaterThanUnsigned | Assembler::traptoEqual,
|
||||
-1, encoding);
|
||||
}
|
||||
return MacroAssembler::is_load_from_polling_page(long_at(0), NULL);
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,18 @@
|
||||
#include <sys/mman.h>
|
||||
|
||||
void SafepointMechanism::pd_initialize() {
|
||||
// No special code needed if we can use SIGTRAP
|
||||
if (ThreadLocalHandshakes && USE_POLL_BIT_ONLY) {
|
||||
default_initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate one protected page
|
||||
char* map_address = (char*)MAP_FAILED;
|
||||
const size_t page_size = os::vm_page_size();
|
||||
const int prot = PROT_READ;
|
||||
const int flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
|
||||
// Use optimized addresses for the polling page,
|
||||
// e.g. map it to a special 32-bit address.
|
||||
if (OptimizePollingPageLocation) {
|
||||
@ -57,14 +67,14 @@ void SafepointMechanism::pd_initialize() {
|
||||
// Try to map with current address wish.
|
||||
// AIX: AIX needs MAP_FIXED if we provide an address and mmap will
|
||||
// fail if the address is already mapped.
|
||||
map_address = (char*) ::mmap(address_wishes[i] - (ssize_t)page_size,
|
||||
page_size, PROT_READ,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
|
||||
map_address = (char*) ::mmap(address_wishes[i],
|
||||
page_size, prot,
|
||||
flags | MAP_FIXED,
|
||||
-1, 0);
|
||||
log_debug(os)("SafePoint Polling Page address: %p (wish) => %p",
|
||||
address_wishes[i], map_address + (ssize_t)page_size);
|
||||
log_debug(os)("SafePoint Polling Page address: %p (wish) => %p",
|
||||
address_wishes[i], map_address);
|
||||
|
||||
if (map_address + (ssize_t)page_size == address_wishes[i]) {
|
||||
if (map_address == address_wishes[i]) {
|
||||
// Map succeeded and map_address is at wished address, exit loop.
|
||||
break;
|
||||
}
|
||||
@ -78,8 +88,17 @@ void SafepointMechanism::pd_initialize() {
|
||||
}
|
||||
}
|
||||
if (map_address == (char*)MAP_FAILED) {
|
||||
map_address = os::reserve_memory(page_size, NULL, page_size);
|
||||
map_address = (char*) ::mmap(NULL, page_size, prot, flags, -1, 0);
|
||||
}
|
||||
guarantee(map_address != (char*)MAP_FAILED, "SafepointMechanism::pd_initialize: failed to allocate polling page");
|
||||
log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(map_address));
|
||||
os::set_polling_page((address)(map_address));
|
||||
|
||||
// Use same page for ThreadLocalHandshakes without SIGTRAP
|
||||
if (ThreadLocalHandshakes) {
|
||||
set_uses_thread_local_poll();
|
||||
intptr_t bad_page_val = reinterpret_cast<intptr_t>(map_address);
|
||||
_poll_armed_value = reinterpret_cast<void*>(bad_page_val | poll_bit());
|
||||
_poll_disarmed_value = NULL; // Readable on AIX
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/osThread.hpp"
|
||||
#include "runtime/safepointMechanism.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
@ -374,9 +375,12 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
|
||||
goto run_stub;
|
||||
}
|
||||
|
||||
else if (sig == SIGSEGV && os::is_poll_address(addr)) {
|
||||
else if ((SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY)
|
||||
? (sig == SIGTRAP && ((NativeInstruction*)pc)->is_safepoint_poll())
|
||||
: (sig == SIGSEGV && os::is_poll_address(addr))) {
|
||||
if (TraceTraps) {
|
||||
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc);
|
||||
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (%s)", p2i(pc),
|
||||
(SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) ? "SIGTRAP" : "SIGSEGV");
|
||||
}
|
||||
stub = SharedRuntime::get_poll_stub(pc);
|
||||
goto run_stub;
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/osThread.hpp"
|
||||
#include "runtime/safepointMechanism.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
@ -382,7 +383,7 @@ JVM_handle_linux_signal(int sig,
|
||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
||||
}
|
||||
|
||||
else if (sig == SIGSEGV &&
|
||||
else if (sig == ((SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) ? SIGTRAP : SIGSEGV) &&
|
||||
// A linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults
|
||||
// in 64bit mode (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6),
|
||||
// especially when we try to read from the safepoint polling page. So the check
|
||||
@ -393,7 +394,8 @@ JVM_handle_linux_signal(int sig,
|
||||
((cb = CodeCache::find_blob(pc)) != NULL) &&
|
||||
cb->is_compiled()) {
|
||||
if (TraceTraps) {
|
||||
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc));
|
||||
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (%s)", p2i(pc),
|
||||
(SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) ? "SIGTRAP" : "SIGSEGV");
|
||||
}
|
||||
stub = SharedRuntime::get_poll_stub(pc);
|
||||
}
|
||||
|
@ -36,23 +36,39 @@ void* SafepointMechanism::_poll_disarmed_value;
|
||||
void SafepointMechanism::default_initialize() {
|
||||
if (ThreadLocalHandshakes) {
|
||||
set_uses_thread_local_poll();
|
||||
const size_t page_size = os::vm_page_size();
|
||||
const size_t allocation_size = 2 * page_size;
|
||||
char* polling_page = os::reserve_memory(allocation_size, NULL, page_size);
|
||||
os::commit_memory_or_exit(polling_page, allocation_size, false, "Unable to commit Safepoint polling page");
|
||||
|
||||
char* bad_page = polling_page;
|
||||
char* good_page = polling_page + page_size;
|
||||
// Poll bit values
|
||||
intptr_t poll_armed_value = poll_bit();
|
||||
intptr_t poll_disarmed_value = 0;
|
||||
|
||||
os::protect_memory(bad_page, page_size, os::MEM_PROT_NONE);
|
||||
os::protect_memory(good_page, page_size, os::MEM_PROT_READ);
|
||||
#ifdef USE_POLL_BIT_ONLY
|
||||
if (!USE_POLL_BIT_ONLY)
|
||||
#endif
|
||||
{
|
||||
// Polling page
|
||||
const size_t page_size = os::vm_page_size();
|
||||
const size_t allocation_size = 2 * page_size;
|
||||
char* polling_page = os::reserve_memory(allocation_size, NULL, page_size);
|
||||
os::commit_memory_or_exit(polling_page, allocation_size, false, "Unable to commit Safepoint polling page");
|
||||
|
||||
log_info(os)("SafePoint Polling address, bad (protected) page:" INTPTR_FORMAT ", good (unprotected) page:" INTPTR_FORMAT, p2i(bad_page), p2i(good_page));
|
||||
os::set_polling_page((address)(bad_page));
|
||||
char* bad_page = polling_page;
|
||||
char* good_page = polling_page + page_size;
|
||||
|
||||
intptr_t poll_page_val = reinterpret_cast<intptr_t>(bad_page);
|
||||
_poll_armed_value = reinterpret_cast<void*>(poll_page_val | poll_bit());
|
||||
_poll_disarmed_value = good_page;
|
||||
os::protect_memory(bad_page, page_size, os::MEM_PROT_NONE);
|
||||
os::protect_memory(good_page, page_size, os::MEM_PROT_READ);
|
||||
|
||||
log_info(os)("SafePoint Polling address, bad (protected) page:" INTPTR_FORMAT ", good (unprotected) page:" INTPTR_FORMAT, p2i(bad_page), p2i(good_page));
|
||||
os::set_polling_page((address)(bad_page));
|
||||
|
||||
// Poll address values
|
||||
intptr_t bad_page_val = reinterpret_cast<intptr_t>(bad_page),
|
||||
good_page_val = reinterpret_cast<intptr_t>(good_page);
|
||||
poll_armed_value |= bad_page_val;
|
||||
poll_disarmed_value |= good_page_val;
|
||||
}
|
||||
|
||||
_poll_armed_value = reinterpret_cast<void*>(poll_armed_value);
|
||||
_poll_disarmed_value = reinterpret_cast<void*>(poll_disarmed_value);
|
||||
} else {
|
||||
const size_t page_size = os::vm_page_size();
|
||||
char* polling_page = os::reserve_memory(page_size, NULL, page_size);
|
||||
|
@ -40,10 +40,7 @@ import jdk.test.lib.process.OutputAnalyzer;
|
||||
public class OsCpuLoggingTest {
|
||||
|
||||
static void analyzeOutputForOsLog(OutputAnalyzer output) throws Exception {
|
||||
// Aix has it's own logging
|
||||
if (!Platform.isAix()) {
|
||||
output.shouldContain("SafePoint Polling address");
|
||||
}
|
||||
output.shouldContain("SafePoint Polling address");
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
@ -58,7 +55,10 @@ public class OsCpuLoggingTest {
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
analyzeOutputForOsCpuLog(output);
|
||||
|
||||
pb = ProcessTools.createJavaProcessBuilder("-Xlog:os", "-version");
|
||||
// PPC64 only uses polling pages when UseSIGTRAP is off.
|
||||
pb = (Platform.isPPC() && Platform.is64bit())
|
||||
? ProcessTools.createJavaProcessBuilder("-Xlog:os", "-XX:-UseSIGTRAP", "-version")
|
||||
: ProcessTools.createJavaProcessBuilder("-Xlog:os", "-version");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
analyzeOutputForOsLog(output);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user