hotspot/src/os/linux/vm/os_linux.cpp
Print this page
*** 20,29 ****
--- 20,31 ----
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
+ # define __STDC_FORMAT_MACROS
+
// do not include precompiled header file
# include "incls/_os_linux.cpp.incl"
// put OS-includes here
# include <sys/types.h>
*** 51,60 ****
--- 53,64 ----
# include <sys/sysinfo.h>
# include <gnu/libc-version.h>
# include <sys/ipc.h>
# include <sys/shm.h>
# include <link.h>
+ # include <stdint.h>
+ # include <inttypes.h>
#define MAX_PATH (2 * K)
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
*** 2490,2499 ****
--- 2494,2591 ----
return ::mmap(addr, size, PROT_NONE,
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0)
!= MAP_FAILED;
}
+ // Linux uses a growable mapping for the stack, and if the mapping for
+ // the stack guard pages is not removed when we detach a thread the
+ // stack cannot grow beyond the pages where the stack guard was
+ // mapped. If at some point later in the process the stack expands to
+ // that point, the Linux kernel cannot expand the stack any further
+ // because the guard pages are in the way, and a segfault occurs.
+ //
+ // However, it's essential not to split the stack region by unmapping
+ // a region (leaving a hole) that's already part of the stack mapping,
+ // so if the stack mapping has already grown beyond the guard pages at
+ // the time we create them, we have to truncate the stack mapping.
+ // So, we need to know the extent of the stack mapping when
+ // create_stack_guard_pages() is called.
+
+ // Find the bounds of the stack mapping. Return true for success.
+ //
+ // We only need this for stacks that are growable: at the time of
+ // writing thread stacks don't use growable mappings (i.e. those
+ // creeated with MAP_GROWSDOWN), and aren't marked "[stack]", so this
+ // only applies to the main thread.
+ static bool
+ get_stack_bounds(uintptr_t *bottom, uintptr_t *top)
+ {
+ char filename[sizeof "/proc/" + sizeof "4294967295" + sizeof "/maps"];
+ snprintf(filename, sizeof filename,
+ "/proc/%d/maps", syscall(SYS_gettid));
+ FILE *f = fopen(filename, "r");
+ if (f == NULL)
+ return false;
+
+ while (!feof(f)) {
+ size_t dummy;
+ char *str = NULL;
+ ssize_t len = getline(&str, &dummy, f);
+ if (len == -1) {
+ return false;
+ }
+
+ if (len > 0 && str[len-1] == '\n') {
+ str[len-1] = 0;
+ len--;
+ }
+
+ static const char *stack_str = "[stack]";
+ if (len > (ssize_t)strlen(stack_str)
+ && (strcmp(str + len - strlen(stack_str), stack_str)
+ == 0)) {
+ if (sscanf(str, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) {
+ uintptr_t sp = (uintptr_t)__builtin_frame_address(0);
+ if (sp >= *bottom && sp <= *top) {
+ free(str);
+ return true;
+ }
+ }
+ }
+
+ free(str);
+ }
+
+ return false;
+ }
+
+ // If the (growable) stack mapping already extends beyond the point
+ // where we're going to put our guard pages, truncate the mapping at
+ // that point my munmap()ping it. This ensures that when we later
+ // munmap() the guard pages we don't leave a hole in the stack
+ // mapping.
+ bool os::create_stack_guard_pages(char* addr, size_t size) {
+ uintptr_t stack_extent, stack_base;
+ if (get_stack_bounds(&stack_extent, &stack_base)) {
+ if (stack_extent < (uintptr_t)addr)
+ ::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent);
+ }
+
+ return os::commit_memory(addr, size);
+ }
+
+ // If this is a growable mapping, remove the guard pages entirely by
+ // munmap()ping them. If not, just call uncommit_memory().
+ bool os::remove_stack_guard_pages(char* addr, size_t size) {
+ uintptr_t stack_extent, stack_base;
+ if (get_stack_bounds(&stack_extent, &stack_base)) {
+ return ::munmap(addr, size) == 0;
+ }
+
+ return os::uncommit_memory(addr, size);
+ }
+
static address _highest_vm_reserved_address = NULL;
// If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
// at 'requested_addr'. If there are existing memory mappings at the same
// location, however, they will be overwritten. If 'fixed' is false,