mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-04 18:55:22 +00:00
8189170: Add option to disable stack overflow checking in primordial thread for use with JNI_CreateJavaJVM
Reviewed-by: stuefe, dcubed
This commit is contained in:
parent
cdf8de893e
commit
687c2c5412
@ -399,7 +399,7 @@ static void query_multipage_support() {
|
||||
// thread (because primordial thread's stack may have different page size than
|
||||
// pthread thread stacks). Running a VM on the primordial thread won't work for a
|
||||
// number of reasons so we may just as well guarantee it here.
|
||||
guarantee0(!os::Aix::is_primordial_thread());
|
||||
guarantee0(!os::is_primordial_thread());
|
||||
|
||||
// Query pthread stack page size. Should be the same as data page size because
|
||||
// pthread stacks are allocated from C-Heap.
|
||||
@ -3448,7 +3448,7 @@ void os::init(void) {
|
||||
|
||||
init_random(1234567);
|
||||
|
||||
// Main_thread points to the aboriginal thread.
|
||||
// _main_thread points to the thread that created/loaded the JVM.
|
||||
Aix::_main_thread = pthread_self();
|
||||
|
||||
initial_time_count = os::elapsed_counter();
|
||||
@ -3995,7 +3995,7 @@ void os::pause() {
|
||||
}
|
||||
}
|
||||
|
||||
bool os::Aix::is_primordial_thread() {
|
||||
bool os::is_primordial_thread(void) {
|
||||
if (pthread_self() == (pthread_t)1) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -99,12 +99,6 @@ class Aix {
|
||||
// Given an address, returns the size of the page backing that address
|
||||
static size_t query_pagesize(void* p);
|
||||
|
||||
// Return `true' if the calling thread is the primordial thread. The
|
||||
// primordial thread is the thread which contains the main function,
|
||||
// *not* necessarily the thread which initialized the VM by calling
|
||||
// JNI_CreateJavaVM.
|
||||
static bool is_primordial_thread(void);
|
||||
|
||||
static int page_size(void) {
|
||||
assert(_page_size != -1, "not initialized");
|
||||
return _page_size;
|
||||
|
||||
@ -3360,7 +3360,7 @@ void os::init(void) {
|
||||
|
||||
Bsd::initialize_system_info();
|
||||
|
||||
// main_thread points to the aboriginal thread
|
||||
// _main_thread points to the thread that created/loaded the JVM.
|
||||
Bsd::_main_thread = pthread_self();
|
||||
|
||||
Bsd::clock_init();
|
||||
|
||||
@ -74,7 +74,6 @@ class Bsd {
|
||||
|
||||
static void hotspot_sigmask(Thread* thread);
|
||||
|
||||
static bool is_initial_thread(void);
|
||||
static pid_t gettid();
|
||||
|
||||
static int page_size(void) { return _page_size; }
|
||||
|
||||
@ -853,8 +853,8 @@ bool os::create_attached_thread(JavaThread* thread) {
|
||||
}
|
||||
}
|
||||
|
||||
if (os::Linux::is_initial_thread()) {
|
||||
// If current thread is initial thread, its stack is mapped on demand,
|
||||
if (os::is_primordial_thread()) {
|
||||
// If current thread is primordial thread, its stack is mapped on demand,
|
||||
// see notes about MAP_GROWSDOWN. Here we try to force kernel to map
|
||||
// the entire stack region to avoid SEGV in stack banging.
|
||||
// It is also useful to get around the heap-stack-gap problem on SuSE
|
||||
@ -915,19 +915,20 @@ void os::free_thread(OSThread* osthread) {
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// initial thread
|
||||
// primordial thread
|
||||
|
||||
// Check if current thread is the initial thread, similar to Solaris thr_main.
|
||||
bool os::Linux::is_initial_thread(void) {
|
||||
// Check if current thread is the primordial thread, similar to Solaris thr_main.
|
||||
bool os::is_primordial_thread(void) {
|
||||
char dummy;
|
||||
// If called before init complete, thread stack bottom will be null.
|
||||
// Can be called if fatal error occurs before initialization.
|
||||
if (initial_thread_stack_bottom() == NULL) return false;
|
||||
assert(initial_thread_stack_bottom() != NULL &&
|
||||
initial_thread_stack_size() != 0,
|
||||
"os::init did not locate initial thread's stack region");
|
||||
if ((address)&dummy >= initial_thread_stack_bottom() &&
|
||||
(address)&dummy < initial_thread_stack_bottom() + initial_thread_stack_size()) {
|
||||
if (os::Linux::initial_thread_stack_bottom() == NULL) return false;
|
||||
assert(os::Linux::initial_thread_stack_bottom() != NULL &&
|
||||
os::Linux::initial_thread_stack_size() != 0,
|
||||
"os::init did not locate primordial thread's stack region");
|
||||
if ((address)&dummy >= os::Linux::initial_thread_stack_bottom() &&
|
||||
(address)&dummy < os::Linux::initial_thread_stack_bottom() +
|
||||
os::Linux::initial_thread_stack_size()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -958,7 +959,7 @@ static bool find_vma(address addr, address* vma_low, address* vma_high) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Locate initial thread stack. This special handling of initial thread stack
|
||||
// Locate primordial thread stack. This special handling of primordial thread stack
|
||||
// is needed because pthread_getattr_np() on most (all?) Linux distros returns
|
||||
// bogus value for the primordial process thread. While the launcher has created
|
||||
// the VM in a new thread since JDK 6, we still have to allow for the use of the
|
||||
@ -982,7 +983,10 @@ void os::Linux::capture_initial_stack(size_t max_size) {
|
||||
// 6308388: a bug in ld.so will relocate its own .data section to the
|
||||
// lower end of primordial stack; reduce ulimit -s value a little bit
|
||||
// so we won't install guard page on ld.so's data section.
|
||||
stack_size -= 2 * page_size();
|
||||
// But ensure we don't underflow the stack size - allow 1 page spare
|
||||
if (stack_size >= (size_t)(3 * page_size())) {
|
||||
stack_size -= 2 * page_size();
|
||||
}
|
||||
|
||||
// Try to figure out where the stack base (top) is. This is harder.
|
||||
//
|
||||
@ -1103,16 +1107,16 @@ void os::Linux::capture_initial_stack(size_t max_size) {
|
||||
|
||||
if (i != 28 - 2) {
|
||||
assert(false, "Bad conversion from /proc/self/stat");
|
||||
// product mode - assume we are the initial thread, good luck in the
|
||||
// product mode - assume we are the primordial thread, good luck in the
|
||||
// embedded case.
|
||||
warning("Can't detect initial thread stack location - bad conversion");
|
||||
warning("Can't detect primordial thread stack location - bad conversion");
|
||||
stack_start = (uintptr_t) &rlim;
|
||||
}
|
||||
} else {
|
||||
// For some reason we can't open /proc/self/stat (for example, running on
|
||||
// FreeBSD with a Linux emulator, or inside chroot), this should work for
|
||||
// most cases, so don't abort:
|
||||
warning("Can't detect initial thread stack location - no /proc/self/stat");
|
||||
warning("Can't detect primordial thread stack location - no /proc/self/stat");
|
||||
stack_start = (uintptr_t) &rlim;
|
||||
}
|
||||
}
|
||||
@ -1132,7 +1136,7 @@ void os::Linux::capture_initial_stack(size_t max_size) {
|
||||
stack_top = (uintptr_t)high;
|
||||
} else {
|
||||
// failed, likely because /proc/self/maps does not exist
|
||||
warning("Can't detect initial thread stack location - find_vma failed");
|
||||
warning("Can't detect primordial thread stack location - find_vma failed");
|
||||
// best effort: stack_start is normally within a few pages below the real
|
||||
// stack top, use it as stack top, and reduce stack size so we won't put
|
||||
// guard page outside stack.
|
||||
@ -3136,10 +3140,10 @@ static address get_stack_commited_bottom(address bottom, size_t size) {
|
||||
// where we're going to put our guard pages, truncate the mapping at
|
||||
// that point by munmap()ping it. This ensures that when we later
|
||||
// munmap() the guard pages we don't leave a hole in the stack
|
||||
// mapping. This only affects the main/initial thread
|
||||
// mapping. This only affects the main/primordial thread
|
||||
|
||||
bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
|
||||
if (os::Linux::is_initial_thread()) {
|
||||
if (os::is_primordial_thread()) {
|
||||
// As we manually grow stack up to bottom inside create_attached_thread(),
|
||||
// it's likely that os::Linux::initial_thread_stack_bottom is mapped and
|
||||
// we don't need to do anything special.
|
||||
@ -3164,14 +3168,14 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
|
||||
|
||||
// If this is a growable mapping, remove the guard pages entirely by
|
||||
// munmap()ping them. If not, just call uncommit_memory(). This only
|
||||
// affects the main/initial thread, but guard against future OS changes
|
||||
// It's safe to always unmap guard pages for initial thread because we
|
||||
// always place it right after end of the mapped region
|
||||
// affects the main/primordial thread, but guard against future OS changes.
|
||||
// It's safe to always unmap guard pages for primordial thread because we
|
||||
// always place it right after end of the mapped region.
|
||||
|
||||
bool os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
uintptr_t stack_extent, stack_base;
|
||||
|
||||
if (os::Linux::is_initial_thread()) {
|
||||
if (os::is_primordial_thread()) {
|
||||
return ::munmap(addr, size) == 0;
|
||||
}
|
||||
|
||||
@ -4860,10 +4864,9 @@ void os::Linux::check_signal_handler(int sig) {
|
||||
extern void report_error(char* file_name, int line_no, char* title,
|
||||
char* format, ...);
|
||||
|
||||
// this is called _before_ the most of global arguments have been parsed
|
||||
// this is called _before_ most of the global arguments have been parsed
|
||||
void os::init(void) {
|
||||
char dummy; // used to get a guess on initial stack address
|
||||
// first_hrtime = gethrtime();
|
||||
|
||||
clock_tics_per_sec = sysconf(_SC_CLK_TCK);
|
||||
|
||||
@ -4880,7 +4883,7 @@ void os::init(void) {
|
||||
|
||||
Linux::initialize_os_info();
|
||||
|
||||
// main_thread points to the aboriginal thread
|
||||
// _main_thread points to the thread that created/loaded the JVM.
|
||||
Linux::_main_thread = pthread_self();
|
||||
|
||||
Linux::clock_init();
|
||||
@ -5851,8 +5854,8 @@ bool os::start_debugging(char *buf, int buflen) {
|
||||
//
|
||||
#ifndef ZERO
|
||||
static void current_stack_region(address * bottom, size_t * size) {
|
||||
if (os::Linux::is_initial_thread()) {
|
||||
// initial thread needs special handling because pthread_getattr_np()
|
||||
if (os::is_primordial_thread()) {
|
||||
// primordial thread needs special handling because pthread_getattr_np()
|
||||
// may return bogus value.
|
||||
*bottom = os::Linux::initial_thread_stack_bottom();
|
||||
*size = os::Linux::initial_thread_stack_size();
|
||||
|
||||
@ -132,7 +132,6 @@ class Linux {
|
||||
|
||||
static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }
|
||||
static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; }
|
||||
static bool is_initial_thread(void);
|
||||
|
||||
static int page_size(void) { return _page_size; }
|
||||
static void set_page_size(int val) { _page_size = val; }
|
||||
|
||||
@ -200,17 +200,21 @@ static inline stack_t get_stack_info() {
|
||||
return st;
|
||||
}
|
||||
|
||||
address os::current_stack_base() {
|
||||
bool os::is_primordial_thread(void) {
|
||||
int r = thr_main();
|
||||
guarantee(r == 0 || r == 1, "CR6501650 or CR6493689");
|
||||
bool is_primordial_thread = r;
|
||||
return r == 1;
|
||||
}
|
||||
|
||||
address os::current_stack_base() {
|
||||
bool _is_primordial_thread = is_primordial_thread();
|
||||
|
||||
// Workaround 4352906, avoid calls to thr_stksegment by
|
||||
// thr_main after the first one (it looks like we trash
|
||||
// some data, causing the value for ss_sp to be incorrect).
|
||||
if (!is_primordial_thread || os::Solaris::_main_stack_base == NULL) {
|
||||
if (!_is_primordial_thread || os::Solaris::_main_stack_base == NULL) {
|
||||
stack_t st = get_stack_info();
|
||||
if (is_primordial_thread) {
|
||||
if (_is_primordial_thread) {
|
||||
// cache initial value of stack base
|
||||
os::Solaris::_main_stack_base = (address)st.ss_sp;
|
||||
}
|
||||
@ -224,9 +228,7 @@ address os::current_stack_base() {
|
||||
size_t os::current_stack_size() {
|
||||
size_t size;
|
||||
|
||||
int r = thr_main();
|
||||
guarantee(r == 0 || r == 1, "CR6501650 or CR6493689");
|
||||
if (!r) {
|
||||
if (!is_primordial_thread()) {
|
||||
size = get_stack_info().ss_size;
|
||||
} else {
|
||||
struct rlimit limits;
|
||||
@ -1102,9 +1104,7 @@ void _handle_uncaught_cxx_exception() {
|
||||
|
||||
// First crack at OS-specific initialization, from inside the new thread.
|
||||
void os::initialize_thread(Thread* thr) {
|
||||
int r = thr_main();
|
||||
guarantee(r == 0 || r == 1, "CR6501650 or CR6493689");
|
||||
if (r) {
|
||||
if (is_primordial_thread()) {
|
||||
JavaThread* jt = (JavaThread *)thr;
|
||||
assert(jt != NULL, "Sanity check");
|
||||
size_t stack_size;
|
||||
@ -4203,6 +4203,7 @@ void os::init(void) {
|
||||
dladdr1_func = CAST_TO_FN_PTR(dladdr1_func_type, dlsym(hdl, "dladdr1"));
|
||||
}
|
||||
|
||||
// main_thread points to the thread that created/loaded the JVM.
|
||||
main_thread = thr_self();
|
||||
|
||||
// dynamic lookup of functions that may not be available in our lowest
|
||||
|
||||
@ -193,7 +193,7 @@ void ThreadLocalAllocBuffer::initialize() {
|
||||
|
||||
set_desired_size(initial_desired_size());
|
||||
|
||||
// Following check is needed because at startup the main (primordial)
|
||||
// Following check is needed because at startup the main
|
||||
// thread is initialized before the heap is. The initialization for
|
||||
// this thread is redone in startup_initialization below.
|
||||
if (Universe::heap() != NULL) {
|
||||
@ -240,7 +240,7 @@ void ThreadLocalAllocBuffer::startup_initialization() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// During jvm startup, the main (primordial) thread is initialized
|
||||
// During jvm startup, the main thread is initialized
|
||||
// before the heap is initialized. So reinitialize it now.
|
||||
guarantee(Thread::current()->is_Java_thread(), "tlab initialization thread not Java thread");
|
||||
Thread::current()->tlab().initialize();
|
||||
|
||||
@ -1178,6 +1178,10 @@ public:
|
||||
"Use detached threads that are recycled upon termination " \
|
||||
"(for Solaris only)") \
|
||||
\
|
||||
experimental(bool, DisablePrimordialThreadGuardPages, false, \
|
||||
"Disable the use of stack guard pages if the JVM is loaded " \
|
||||
"on the primordial process thread") \
|
||||
\
|
||||
product(bool, UseLWPSynchronization, true, \
|
||||
"Use LWP-based instead of libthread-based synchronization " \
|
||||
"(SPARC only)") \
|
||||
|
||||
@ -454,7 +454,24 @@ class os: AllStatic {
|
||||
static bool create_thread(Thread* thread,
|
||||
ThreadType thr_type,
|
||||
size_t req_stack_size = 0);
|
||||
|
||||
// The "main thread", also known as "starting thread", is the thread
|
||||
// that loads/creates the JVM via JNI_CreateJavaVM.
|
||||
static bool create_main_thread(JavaThread* thread);
|
||||
|
||||
// The primordial thread is the initial process thread. The java
|
||||
// launcher never uses the primordial thread as the main thread, but
|
||||
// applications that host the JVM directly may do so. Some platforms
|
||||
// need special-case handling of the primordial thread if it attaches
|
||||
// to the VM.
|
||||
static bool is_primordial_thread(void)
|
||||
#if defined(_WINDOWS) || defined(BSD)
|
||||
// No way to identify the primordial thread.
|
||||
{ return false; }
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
static bool create_attached_thread(JavaThread* thread);
|
||||
static void pd_start_thread(Thread* thread);
|
||||
static void start_thread(Thread* thread);
|
||||
|
||||
@ -2471,7 +2471,13 @@ size_t JavaThread::_stack_reserved_zone_size = 0;
|
||||
size_t JavaThread::_stack_shadow_zone_size = 0;
|
||||
|
||||
void JavaThread::create_stack_guard_pages() {
|
||||
if (!os::uses_stack_guard_pages() || _stack_guard_state != stack_guard_unused) { return; }
|
||||
if (!os::uses_stack_guard_pages() ||
|
||||
_stack_guard_state != stack_guard_unused ||
|
||||
(DisablePrimordialThreadGuardPages && os::is_primordial_thread())) {
|
||||
log_info(os, thread)("Stack guard page creation for thread "
|
||||
UINTX_FORMAT " disabled", os::current_thread_id());
|
||||
return;
|
||||
}
|
||||
address low_addr = stack_end();
|
||||
size_t len = stack_guard_zone_size();
|
||||
|
||||
|
||||
@ -156,7 +156,8 @@ inline size_t JavaThread::stack_available(address cur_sp) {
|
||||
|
||||
inline bool JavaThread::stack_guards_enabled() {
|
||||
#ifdef ASSERT
|
||||
if (os::uses_stack_guard_pages()) {
|
||||
if (os::uses_stack_guard_pages() &&
|
||||
!(DisablePrimordialThreadGuardPages && os::is_primordial_thread())) {
|
||||
assert(_stack_guard_state != stack_guard_unused, "guard pages must be in use");
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user