Mercurial > hg > graal-compiler
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 |