Mercurial > hg > graal-jvmci-8
comparison src/os/linux/vm/os_linux.cpp @ 10969:a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
Summary: Detect mmap() commit failures in Linux and Solaris os::commit_memory() impls and call vm_exit_out_of_memory(). Add os::commit_memory_or_exit(). Also tidy up some NMT accounting and some mmap() return value checking.
Reviewed-by: zgu, stefank, dholmes, dsamersoff
author | dcubed |
---|---|
date | Thu, 13 Jun 2013 11:16:38 -0700 |
parents | f2110083203d |
children | 1f4355cee9a2 |
comparison
equal
deleted
inserted
replaced
10405:f2110083203d | 10969:a837fa3d3f86 |
---|---|
2610 ::close(fd); | 2610 ::close(fd); |
2611 unlink(buf); | 2611 unlink(buf); |
2612 } | 2612 } |
2613 } | 2613 } |
2614 | 2614 |
2615 static bool recoverable_mmap_error(int err) { | |
2616 // See if the error is one we can let the caller handle. This | |
2617 // list of errno values comes from JBS-6843484. I can't find a | |
2618 // Linux man page that documents this specific set of errno | |
2619 // values so while this list currently matches Solaris, it may | |
2620 // change as we gain experience with this failure mode. | |
2621 switch (err) { | |
2622 case EBADF: | |
2623 case EINVAL: | |
2624 case ENOTSUP: | |
2625 // let the caller deal with these errors | |
2626 return true; | |
2627 | |
2628 default: | |
2629 // Any remaining errors on this OS can cause our reserved mapping | |
2630 // to be lost. That can cause confusion where different data | |
2631 // structures think they have the same memory mapped. The worst | |
2632 // scenario is if both the VM and a library think they have the | |
2633 // same memory mapped. | |
2634 return false; | |
2635 } | |
2636 } | |
2637 | |
2638 static void warn_fail_commit_memory(char* addr, size_t size, bool exec, | |
2639 int err) { | |
2640 warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT | |
2641 ", %d) failed; error='%s' (errno=%d)", addr, size, exec, | |
2642 strerror(err), err); | |
2643 } | |
2644 | |
2645 static void warn_fail_commit_memory(char* addr, size_t size, | |
2646 size_t alignment_hint, bool exec, | |
2647 int err) { | |
2648 warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT | |
2649 ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, size, | |
2650 alignment_hint, exec, strerror(err), err); | |
2651 } | |
2652 | |
2615 // NOTE: Linux kernel does not really reserve the pages for us. | 2653 // NOTE: Linux kernel does not really reserve the pages for us. |
2616 // All it does is to check if there are enough free pages | 2654 // All it does is to check if there are enough free pages |
2617 // left at the time of mmap(). This could be a potential | 2655 // left at the time of mmap(). This could be a potential |
2618 // problem. | 2656 // problem. |
2619 bool os::pd_commit_memory(char* addr, size_t size, bool exec) { | 2657 int os::Linux::commit_memory_impl(char* addr, size_t size, bool exec) { |
2620 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; | 2658 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; |
2621 uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, | 2659 uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, |
2622 MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); | 2660 MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); |
2623 if (res != (uintptr_t) MAP_FAILED) { | 2661 if (res != (uintptr_t) MAP_FAILED) { |
2624 if (UseNUMAInterleaving) { | 2662 if (UseNUMAInterleaving) { |
2625 numa_make_global(addr, size); | 2663 numa_make_global(addr, size); |
2626 } | 2664 } |
2627 return true; | 2665 return 0; |
2628 } | 2666 } |
2629 return false; | 2667 |
2668 int err = errno; // save errno from mmap() call above | |
2669 | |
2670 if (!recoverable_mmap_error(err)) { | |
2671 warn_fail_commit_memory(addr, size, exec, err); | |
2672 vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "committing reserved memory."); | |
2673 } | |
2674 | |
2675 return err; | |
2676 } | |
2677 | |
2678 bool os::pd_commit_memory(char* addr, size_t size, bool exec) { | |
2679 return os::Linux::commit_memory_impl(addr, size, exec) == 0; | |
2680 } | |
2681 | |
2682 void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec, | |
2683 const char* mesg) { | |
2684 assert(mesg != NULL, "mesg must be specified"); | |
2685 int err = os::Linux::commit_memory_impl(addr, size, exec); | |
2686 if (err != 0) { | |
2687 // the caller wants all commit errors to exit with the specified mesg: | |
2688 warn_fail_commit_memory(addr, size, exec, err); | |
2689 vm_exit_out_of_memory(size, OOM_MMAP_ERROR, mesg); | |
2690 } | |
2630 } | 2691 } |
2631 | 2692 |
2632 // Define MAP_HUGETLB here so we can build HotSpot on old systems. | 2693 // Define MAP_HUGETLB here so we can build HotSpot on old systems. |
2633 #ifndef MAP_HUGETLB | 2694 #ifndef MAP_HUGETLB |
2634 #define MAP_HUGETLB 0x40000 | 2695 #define MAP_HUGETLB 0x40000 |
2637 // Define MADV_HUGEPAGE here so we can build HotSpot on old systems. | 2698 // Define MADV_HUGEPAGE here so we can build HotSpot on old systems. |
2638 #ifndef MADV_HUGEPAGE | 2699 #ifndef MADV_HUGEPAGE |
2639 #define MADV_HUGEPAGE 14 | 2700 #define MADV_HUGEPAGE 14 |
2640 #endif | 2701 #endif |
2641 | 2702 |
2642 bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, | 2703 int os::Linux::commit_memory_impl(char* addr, size_t size, |
2643 bool exec) { | 2704 size_t alignment_hint, bool exec) { |
2705 int err; | |
2644 if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { | 2706 if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { |
2645 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; | 2707 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; |
2646 uintptr_t res = | 2708 uintptr_t res = |
2647 (uintptr_t) ::mmap(addr, size, prot, | 2709 (uintptr_t) ::mmap(addr, size, prot, |
2648 MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB, | 2710 MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB, |
2649 -1, 0); | 2711 -1, 0); |
2650 if (res != (uintptr_t) MAP_FAILED) { | 2712 if (res != (uintptr_t) MAP_FAILED) { |
2651 if (UseNUMAInterleaving) { | 2713 if (UseNUMAInterleaving) { |
2652 numa_make_global(addr, size); | 2714 numa_make_global(addr, size); |
2653 } | 2715 } |
2654 return true; | 2716 return 0; |
2717 } | |
2718 | |
2719 err = errno; // save errno from mmap() call above | |
2720 | |
2721 if (!recoverable_mmap_error(err)) { | |
2722 // However, it is not clear that this loss of our reserved mapping | |
2723 // happens with large pages on Linux or that we cannot recover | |
2724 // from the loss. For now, we just issue a warning and we don't | |
2725 // call vm_exit_out_of_memory(). This issue is being tracked by | |
2726 // JBS-8007074. | |
2727 warn_fail_commit_memory(addr, size, alignment_hint, exec, err); | |
2728 // vm_exit_out_of_memory(size, OOM_MMAP_ERROR, | |
2729 // "committing reserved memory."); | |
2655 } | 2730 } |
2656 // Fall through and try to use small pages | 2731 // Fall through and try to use small pages |
2657 } | 2732 } |
2658 | 2733 |
2659 if (commit_memory(addr, size, exec)) { | 2734 err = os::Linux::commit_memory_impl(addr, size, exec); |
2735 if (err == 0) { | |
2660 realign_memory(addr, size, alignment_hint); | 2736 realign_memory(addr, size, alignment_hint); |
2661 return true; | 2737 } |
2662 } | 2738 return err; |
2663 return false; | 2739 } |
2740 | |
2741 bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, | |
2742 bool exec) { | |
2743 return os::Linux::commit_memory_impl(addr, size, alignment_hint, exec) == 0; | |
2744 } | |
2745 | |
2746 void os::pd_commit_memory_or_exit(char* addr, size_t size, | |
2747 size_t alignment_hint, bool exec, | |
2748 const char* mesg) { | |
2749 assert(mesg != NULL, "mesg must be specified"); | |
2750 int err = os::Linux::commit_memory_impl(addr, size, alignment_hint, exec); | |
2751 if (err != 0) { | |
2752 // the caller wants all commit errors to exit with the specified mesg: | |
2753 warn_fail_commit_memory(addr, size, alignment_hint, exec, err); | |
2754 vm_exit_out_of_memory(size, OOM_MMAP_ERROR, mesg); | |
2755 } | |
2664 } | 2756 } |
2665 | 2757 |
2666 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { | 2758 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { |
2667 if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { | 2759 if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { |
2668 // We don't check the return value: madvise(MADV_HUGEPAGE) may not | 2760 // We don't check the return value: madvise(MADV_HUGEPAGE) may not |
2676 // the existing pages. However it won't work for SHM-based large pages that cannot be | 2768 // the existing pages. However it won't work for SHM-based large pages that cannot be |
2677 // uncommitted at all. We don't do anything in this case to avoid creating a segment with | 2769 // uncommitted at all. We don't do anything in this case to avoid creating a segment with |
2678 // small pages on top of the SHM segment. This method always works for small pages, so we | 2770 // small pages on top of the SHM segment. This method always works for small pages, so we |
2679 // allow that in any case. | 2771 // allow that in any case. |
2680 if (alignment_hint <= (size_t)os::vm_page_size() || !UseSHM) { | 2772 if (alignment_hint <= (size_t)os::vm_page_size() || !UseSHM) { |
2681 commit_memory(addr, bytes, alignment_hint, false); | 2773 commit_memory(addr, bytes, alignment_hint, !ExecMem); |
2682 } | 2774 } |
2683 } | 2775 } |
2684 | 2776 |
2685 void os::numa_make_global(char *addr, size_t bytes) { | 2777 void os::numa_make_global(char *addr, size_t bytes) { |
2686 Linux::numa_interleave_memory(addr, bytes); | 2778 Linux::numa_interleave_memory(addr, bytes); |
2929 "growable stack in non-initial thread"); | 3021 "growable stack in non-initial thread"); |
2930 if (stack_extent < (uintptr_t)addr) | 3022 if (stack_extent < (uintptr_t)addr) |
2931 ::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent); | 3023 ::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent); |
2932 } | 3024 } |
2933 | 3025 |
2934 return os::commit_memory(addr, size); | 3026 return os::commit_memory(addr, size, !ExecMem); |
2935 } | 3027 } |
2936 | 3028 |
2937 // If this is a growable mapping, remove the guard pages entirely by | 3029 // If this is a growable mapping, remove the guard pages entirely by |
2938 // munmap()ping them. If not, just call uncommit_memory(). This only | 3030 // munmap()ping them. If not, just call uncommit_memory(). This only |
2939 // affects the main/initial thread, but guard against future OS changes | 3031 // affects the main/initial thread, but guard against future OS changes |
3051 bool result = false; | 3143 bool result = false; |
3052 void *p = mmap (NULL, page_size, PROT_READ|PROT_WRITE, | 3144 void *p = mmap (NULL, page_size, PROT_READ|PROT_WRITE, |
3053 MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, | 3145 MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, |
3054 -1, 0); | 3146 -1, 0); |
3055 | 3147 |
3056 if (p != (void *) -1) { | 3148 if (p != MAP_FAILED) { |
3057 // We don't know if this really is a huge page or not. | 3149 // We don't know if this really is a huge page or not. |
3058 FILE *fp = fopen("/proc/self/maps", "r"); | 3150 FILE *fp = fopen("/proc/self/maps", "r"); |
3059 if (fp) { | 3151 if (fp) { |
3060 while (!feof(fp)) { | 3152 while (!feof(fp)) { |
3061 char chars[257]; | 3153 char chars[257]; |
4391 tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page); | 4483 tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page); |
4392 #endif | 4484 #endif |
4393 | 4485 |
4394 if (!UseMembar) { | 4486 if (!UseMembar) { |
4395 address mem_serialize_page = (address) ::mmap(NULL, Linux::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | 4487 address mem_serialize_page = (address) ::mmap(NULL, Linux::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); |
4396 guarantee( mem_serialize_page != NULL, "mmap Failed for memory serialize page"); | 4488 guarantee( mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); |
4397 os::set_memory_serialize_page( mem_serialize_page ); | 4489 os::set_memory_serialize_page( mem_serialize_page ); |
4398 | 4490 |
4399 #ifndef PRODUCT | 4491 #ifndef PRODUCT |
4400 if(Verbose && PrintMiscellaneous) | 4492 if(Verbose && PrintMiscellaneous) |
4401 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); | 4493 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); |