# HG changeset patch # User stuefe # Date 1498659174 -7200 # Node ID 0b817584e8a94161f587e6df8a6a570753e58de7 # Parent d6fb8a7a784336ced3975bdaf723d0bd520f54fb 8182984: [aix] Make stack traces independent on successful vm initialization Reviewed-by: simonis, mdoerr, clanger diff -r d6fb8a7a7843 -r 0b817584e8a9 hotspot/src/os/aix/vm/os_aix.cpp --- a/hotspot/src/os/aix/vm/os_aix.cpp Wed Jun 28 14:15:56 2017 +0200 +++ b/hotspot/src/os/aix/vm/os_aix.cpp Wed Jun 28 16:12:54 2017 +0200 @@ -130,8 +130,6 @@ #define ERROR_MP_VMGETINFO_FAILED 102 #define ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K 103 -// Query dimensions of the stack of the calling thread. -static bool query_stack_dimensions(address* p_stack_base, size_t* p_stack_size); static address resolve_function_descriptor_to_code_pointer(address p); static void vmembk_print_on(outputStream* os); @@ -764,11 +762,8 @@ // find out my own stack dimensions { // actually, this should do exactly the same as thread->record_stack_base_and_size... - address base = 0; - size_t size = 0; - query_stack_dimensions(&base, &size); - thread->set_stack_base(base); - thread->set_stack_size(size); + thread->set_stack_base(os::current_stack_base()); + thread->set_stack_size(os::current_stack_size()); } const pthread_t pthread_id = ::pthread_self(); @@ -4297,91 +4292,28 @@ ///////////////////////////////////////////////////////////////////////////// // thread stack -// Function to query the current stack size using pthread_getthrds_np. -static bool query_stack_dimensions(address* p_stack_base, size_t* p_stack_size) { - - // Information about this api can be found (a) in the pthread.h header and - // (b) in http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/pthread_getthrds_np.htm - // - // The use of this API to find out the current stack is kind of undefined. - // But after a lot of tries and asking IBM about it, I concluded that it is safe - // enough for cases where I let the pthread library create its stacks. For cases - // where I create an own stack and pass this to pthread_create, it seems not to - // work (the returned stack size in that case is 0). - - pthread_t tid = pthread_self(); - struct __pthrdsinfo pinfo; - char dummy[1]; // Just needed to satisfy pthread_getthrds_np. - int dummy_size = sizeof(dummy); - - memset(&pinfo, 0, sizeof(pinfo)); - - const int rc = pthread_getthrds_np(&tid, PTHRDSINFO_QUERY_ALL, &pinfo, - sizeof(pinfo), dummy, &dummy_size); - - if (rc != 0) { - trcVerbose("pthread_getthrds_np failed (%d)", rc); - return false; - } - guarantee0(pinfo.__pi_stackend); - - // The following may happen when invoking pthread_getthrds_np on a pthread - // running on a user provided stack (when handing down a stack to pthread - // create, see pthread_attr_setstackaddr). - // Not sure what to do then. - - guarantee0(pinfo.__pi_stacksize); - - // Note: we get three values from pthread_getthrds_np: - // __pi_stackaddr, __pi_stacksize, __pi_stackend - // - // high addr --------------------- - // - // | pthread internal data, like ~2K - // | - // | --------------------- __pi_stackend (usually not page aligned, (xxxxF890)) - // | - // | - // | - // | - // | - // | - // | --------------------- (__pi_stackend - __pi_stacksize) - // | - // | padding to align the following AIX guard pages, if enabled. - // | - // V --------------------- __pi_stackaddr - // - // low addr AIX guard pages, if enabled (AIXTHREAD_GUARDPAGES > 0) - // - - address stack_base = (address)(pinfo.__pi_stackend); - address stack_low_addr = (address)align_ptr_up(pinfo.__pi_stackaddr, - os::vm_page_size()); - size_t stack_size = stack_base - stack_low_addr; - - if (p_stack_base) { - *p_stack_base = stack_base; - } - - if (p_stack_size) { - *p_stack_size = stack_size; - } - - return true; -} - // Get the current stack base from the OS (actually, the pthread library). +// Note: usually not page aligned. address os::current_stack_base() { - address p; - query_stack_dimensions(&p, 0); - return p; + AixMisc::stackbounds_t bounds; + bool rc = AixMisc::query_stack_bounds_for_current_thread(&bounds); + guarantee(rc, "Unable to retrieve stack bounds."); + return bounds.base; } // Get the current stack size from the OS (actually, the pthread library). +// Returned size is such that (base - size) is always aligned to page size. size_t os::current_stack_size() { - size_t s; - query_stack_dimensions(0, &s); + AixMisc::stackbounds_t bounds; + bool rc = AixMisc::query_stack_bounds_for_current_thread(&bounds); + guarantee(rc, "Unable to retrieve stack bounds."); + // Align the returned stack size such that the stack low address + // is aligned to page size (Note: base is usually not and we do not care). + // We need to do this because caller code will assume stack low address is + // page aligned and will place guard pages without checking. + address low = bounds.base - bounds.size; + address low_aligned = (address)align_ptr_up(low, os::vm_page_size()); + size_t s = bounds.base - low_aligned; return s; } diff -r d6fb8a7a7843 -r 0b817584e8a9 hotspot/src/os/aix/vm/porting_aix.cpp --- a/hotspot/src/os/aix/vm/porting_aix.cpp Wed Jun 28 14:15:56 2017 +0200 +++ b/hotspot/src/os/aix/vm/porting_aix.cpp Wed Jun 28 16:12:54 2017 +0200 @@ -35,6 +35,7 @@ #include #include +#include #include ////////////////////////////////// @@ -680,13 +681,14 @@ // retrieve it from the OS. stackptr_t stack_base = NULL; size_t stack_size = NULL; - Thread* const thread = Thread::current_or_null_safe(); - if (thread) { - stack_base = (stackptr_t) thread->stack_base(); - stack_size = thread->stack_size(); - } else { - stack_base = (stackptr_t) os::current_stack_base(); - stack_size = os::current_stack_size(); + { + AixMisc::stackbounds_t stackbounds; + if (!AixMisc::query_stack_bounds_for_current_thread(&stackbounds)) { + st->print_cr("Cannot retrieve stack bounds."); + return; + } + stack_base = (stackptr_t)stackbounds.base; + stack_size = stackbounds.size; } st->print_cr("------ current frame:"); @@ -809,5 +811,73 @@ } +bool AixMisc::query_stack_bounds_for_current_thread(stackbounds_t* out) { + + // Information about this api can be found (a) in the pthread.h header and + // (b) in http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/pthread_getthrds_np.htm + // + // The use of this API to find out the current stack is kind of undefined. + // But after a lot of tries and asking IBM about it, I concluded that it is safe + // enough for cases where I let the pthread library create its stacks. For cases + // where I create an own stack and pass this to pthread_create, it seems not to + // work (the returned stack size in that case is 0). + + pthread_t tid = pthread_self(); + struct __pthrdsinfo pinfo; + char dummy[1]; // Just needed to satisfy pthread_getthrds_np. + int dummy_size = sizeof(dummy); + + memset(&pinfo, 0, sizeof(pinfo)); + + const int rc = pthread_getthrds_np(&tid, PTHRDSINFO_QUERY_ALL, &pinfo, + sizeof(pinfo), dummy, &dummy_size); + + if (rc != 0) { + fprintf(stderr, "pthread_getthrds_np failed (%d)\n", rc); + fflush(stdout); + return false; + } + + // The following may happen when invoking pthread_getthrds_np on a pthread + // running on a user provided stack (when handing down a stack to pthread + // create, see pthread_attr_setstackaddr). + // Not sure what to do then. + if (pinfo.__pi_stackend == NULL || pinfo.__pi_stackaddr == NULL) { + fprintf(stderr, "pthread_getthrds_np - invalid values\n"); + fflush(stdout); + return false; + } + + // Note: we get three values from pthread_getthrds_np: + // __pi_stackaddr, __pi_stacksize, __pi_stackend + // + // high addr --------------------- base, high + // + // | pthread internal data, like ~2K + // | + // | --------------------- __pi_stackend (usually not page aligned, (xxxxF890)) + // | + // | + // | + // | + // | + // | + // | --------------------- (__pi_stackend - __pi_stacksize) + // | + // | padding to align the following AIX guard pages, if enabled. + // | + // V --------------------- __pi_stackaddr low, base - size + // + // low addr AIX guard pages, if enabled (AIXTHREAD_GUARDPAGES > 0) + // + + out->base = (address)pinfo.__pi_stackend; + address low = (address)pinfo.__pi_stackaddr; + out->size = out->base - low; + return true; + +} + + diff -r d6fb8a7a7843 -r 0b817584e8a9 hotspot/src/os/aix/vm/porting_aix.hpp --- a/hotspot/src/os/aix/vm/porting_aix.hpp Wed Jun 28 14:15:56 2017 +0200 +++ b/hotspot/src/os/aix/vm/porting_aix.hpp Wed Jun 28 16:12:54 2017 +0200 @@ -87,11 +87,25 @@ class AixNativeCallstack { public: + // This function can be used independently from os::init(); static void print_callstack_for_context(outputStream* st, const ucontext_t* uc, bool demangle, char* buf, size_t buf_size); }; +class AixMisc { + public: + struct stackbounds_t { + address base; // high address (stack grows down) + size_t size; + }; + + // Invokes pthread_getthrds_np() and returns its values. Note: values are + // not aligned to stack page sizes. + // This function can be used independently from os::init(); + static bool query_stack_bounds_for_current_thread(stackbounds_t* out); + +}; #endif // OS_AIX_VM_PORTING_AIX_HPP