comparison src/os/linux/vm/os_linux.cpp @ 1320:3b3d12e645e7

6929067: Stack guard pages should be removed when thread is detached Summary: Add code to unmap stack guard area when thread is detached. Reviewed-by: coleenp, kamg
author coleenp
date Fri, 12 Mar 2010 10:42:16 -0500
parents 167c2986d91b
children 98ba8ca25feb
comparison
equal deleted inserted replaced
1292:12d91eb0f579 1320:3b3d12e645e7
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or 20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions. 21 * have any questions.
22 * 22 *
23 */ 23 */
24
25 # define __STDC_FORMAT_MACROS
24 26
25 // do not include precompiled header file 27 // do not include precompiled header file
26 # include "incls/_os_linux.cpp.incl" 28 # include "incls/_os_linux.cpp.incl"
27 29
28 // put OS-includes here 30 // put OS-includes here
51 # include <sys/sysinfo.h> 53 # include <sys/sysinfo.h>
52 # include <gnu/libc-version.h> 54 # include <gnu/libc-version.h>
53 # include <sys/ipc.h> 55 # include <sys/ipc.h>
54 # include <sys/shm.h> 56 # include <sys/shm.h>
55 # include <link.h> 57 # include <link.h>
58 # include <stdint.h>
59 # include <inttypes.h>
56 60
57 #define MAX_PATH (2 * K) 61 #define MAX_PATH (2 * K)
58 62
59 // for timer info max values which include all bits 63 // for timer info max values which include all bits
60 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) 64 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
2488 2492
2489 bool os::uncommit_memory(char* addr, size_t size) { 2493 bool os::uncommit_memory(char* addr, size_t size) {
2490 return ::mmap(addr, size, PROT_NONE, 2494 return ::mmap(addr, size, PROT_NONE,
2491 MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0) 2495 MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0)
2492 != MAP_FAILED; 2496 != MAP_FAILED;
2497 }
2498
2499 // Linux uses a growable mapping for the stack, and if the mapping for
2500 // the stack guard pages is not removed when we detach a thread the
2501 // stack cannot grow beyond the pages where the stack guard was
2502 // mapped. If at some point later in the process the stack expands to
2503 // that point, the Linux kernel cannot expand the stack any further
2504 // because the guard pages are in the way, and a segfault occurs.
2505 //
2506 // However, it's essential not to split the stack region by unmapping
2507 // a region (leaving a hole) that's already part of the stack mapping,
2508 // so if the stack mapping has already grown beyond the guard pages at
2509 // the time we create them, we have to truncate the stack mapping.
2510 // So, we need to know the extent of the stack mapping when
2511 // create_stack_guard_pages() is called.
2512
2513 // Find the bounds of the stack mapping. Return true for success.
2514 //
2515 // We only need this for stacks that are growable: at the time of
2516 // writing thread stacks don't use growable mappings (i.e. those
2517 // creeated with MAP_GROWSDOWN), and aren't marked "[stack]", so this
2518 // only applies to the main thread.
2519 static bool
2520 get_stack_bounds(uintptr_t *bottom, uintptr_t *top)
2521 {
2522 FILE *f = fopen("/proc/self/maps", "r");
2523 if (f == NULL)
2524 return false;
2525
2526 while (!feof(f)) {
2527 size_t dummy;
2528 char *str = NULL;
2529 ssize_t len = getline(&str, &dummy, f);
2530 if (len == -1) {
2531 return false;
2532 }
2533
2534 if (len > 0 && str[len-1] == '\n') {
2535 str[len-1] = 0;
2536 len--;
2537 }
2538
2539 static const char *stack_str = "[stack]";
2540 if (len > (ssize_t)strlen(stack_str)
2541 && (strcmp(str + len - strlen(stack_str), stack_str) == 0)) {
2542 if (sscanf(str, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) {
2543 uintptr_t sp = (uintptr_t)__builtin_frame_address(0);
2544 if (sp >= *bottom && sp <= *top) {
2545 free(str);
2546 return true;
2547 }
2548 }
2549 }
2550
2551 free(str);
2552 }
2553
2554 return false;
2555 }
2556
2557 // If the (growable) stack mapping already extends beyond the point
2558 // where we're going to put our guard pages, truncate the mapping at
2559 // that point by munmap()ping it. This ensures that when we later
2560 // munmap() the guard pages we don't leave a hole in the stack
2561 // mapping.
2562 bool os::create_stack_guard_pages(char* addr, size_t size) {
2563 uintptr_t stack_extent, stack_base;
2564 if (get_stack_bounds(&stack_extent, &stack_base)) {
2565 if (stack_extent < (uintptr_t)addr)
2566 ::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent);
2567 }
2568
2569 return os::commit_memory(addr, size);
2570 }
2571
2572 // If this is a growable mapping, remove the guard pages entirely by
2573 // munmap()ping them. If not, just call uncommit_memory().
2574 bool os::remove_stack_guard_pages(char* addr, size_t size) {
2575 uintptr_t stack_extent, stack_base;
2576 if (get_stack_bounds(&stack_extent, &stack_base)) {
2577 return ::munmap(addr, size) == 0;
2578 }
2579
2580 return os::uncommit_memory(addr, size);
2493 } 2581 }
2494 2582
2495 static address _highest_vm_reserved_address = NULL; 2583 static address _highest_vm_reserved_address = NULL;
2496 2584
2497 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory 2585 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory