Mercurial > hg > graal-jvmci-8
comparison src/os/solaris/vm/os_solaris.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 | e95fc50106cf |
comparison
equal
deleted
inserted
replaced
10405:f2110083203d | 10969:a837fa3d3f86 |
---|---|
2782 int os::vm_allocation_granularity() { | 2782 int os::vm_allocation_granularity() { |
2783 assert(page_size != -1, "must call os::init"); | 2783 assert(page_size != -1, "must call os::init"); |
2784 return page_size; | 2784 return page_size; |
2785 } | 2785 } |
2786 | 2786 |
2787 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) { | 2787 static bool recoverable_mmap_error(int err) { |
2788 // See if the error is one we can let the caller handle. This | |
2789 // list of errno values comes from the Solaris mmap(2) man page. | |
2790 switch (err) { | |
2791 case EBADF: | |
2792 case EINVAL: | |
2793 case ENOTSUP: | |
2794 // let the caller deal with these errors | |
2795 return true; | |
2796 | |
2797 default: | |
2798 // Any remaining errors on this OS can cause our reserved mapping | |
2799 // to be lost. That can cause confusion where different data | |
2800 // structures think they have the same memory mapped. The worst | |
2801 // scenario is if both the VM and a library think they have the | |
2802 // same memory mapped. | |
2803 return false; | |
2804 } | |
2805 } | |
2806 | |
2807 static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec, | |
2808 int err) { | |
2809 warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT | |
2810 ", %d) failed; error='%s' (errno=%d)", addr, bytes, exec, | |
2811 strerror(err), err); | |
2812 } | |
2813 | |
2814 static void warn_fail_commit_memory(char* addr, size_t bytes, | |
2815 size_t alignment_hint, bool exec, | |
2816 int err) { | |
2817 warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT | |
2818 ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, bytes, | |
2819 alignment_hint, exec, strerror(err), err); | |
2820 } | |
2821 | |
2822 int os::Solaris::commit_memory_impl(char* addr, size_t bytes, bool exec) { | |
2788 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; | 2823 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; |
2789 size_t size = bytes; | 2824 size_t size = bytes; |
2790 char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); | 2825 char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); |
2791 if (res != NULL) { | 2826 if (res != NULL) { |
2792 if (UseNUMAInterleaving) { | 2827 if (UseNUMAInterleaving) { |
2793 numa_make_global(addr, bytes); | 2828 numa_make_global(addr, bytes); |
2794 } | 2829 } |
2795 return true; | 2830 return 0; |
2796 } | 2831 } |
2797 return false; | 2832 |
2798 } | 2833 int err = errno; // save errno from mmap() call in mmap_chunk() |
2799 | 2834 |
2800 bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint, | 2835 if (!recoverable_mmap_error(err)) { |
2801 bool exec) { | 2836 warn_fail_commit_memory(addr, bytes, exec, err); |
2802 if (commit_memory(addr, bytes, exec)) { | 2837 vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, "committing reserved memory."); |
2838 } | |
2839 | |
2840 return err; | |
2841 } | |
2842 | |
2843 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) { | |
2844 return Solaris::commit_memory_impl(addr, bytes, exec) == 0; | |
2845 } | |
2846 | |
2847 void os::pd_commit_memory_or_exit(char* addr, size_t bytes, bool exec, | |
2848 const char* mesg) { | |
2849 assert(mesg != NULL, "mesg must be specified"); | |
2850 int err = os::Solaris::commit_memory_impl(addr, bytes, exec); | |
2851 if (err != 0) { | |
2852 // the caller wants all commit errors to exit with the specified mesg: | |
2853 warn_fail_commit_memory(addr, bytes, exec, err); | |
2854 vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, mesg); | |
2855 } | |
2856 } | |
2857 | |
2858 int os::Solaris::commit_memory_impl(char* addr, size_t bytes, | |
2859 size_t alignment_hint, bool exec) { | |
2860 int err = Solaris::commit_memory_impl(addr, bytes, exec); | |
2861 if (err == 0) { | |
2803 if (UseMPSS && alignment_hint > (size_t)vm_page_size()) { | 2862 if (UseMPSS && alignment_hint > (size_t)vm_page_size()) { |
2804 // If the large page size has been set and the VM | 2863 // If the large page size has been set and the VM |
2805 // is using large pages, use the large page size | 2864 // is using large pages, use the large page size |
2806 // if it is smaller than the alignment hint. This is | 2865 // if it is smaller than the alignment hint. This is |
2807 // a case where the VM wants to use a larger alignment size | 2866 // a case where the VM wants to use a larger alignment size |
2819 page_size = alignment_hint; | 2878 page_size = alignment_hint; |
2820 } | 2879 } |
2821 // Since this is a hint, ignore any failures. | 2880 // Since this is a hint, ignore any failures. |
2822 (void)Solaris::set_mpss_range(addr, bytes, page_size); | 2881 (void)Solaris::set_mpss_range(addr, bytes, page_size); |
2823 } | 2882 } |
2824 return true; | 2883 } |
2825 } | 2884 return err; |
2826 return false; | 2885 } |
2886 | |
2887 bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint, | |
2888 bool exec) { | |
2889 return Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec) == 0; | |
2890 } | |
2891 | |
2892 void os::pd_commit_memory_or_exit(char* addr, size_t bytes, | |
2893 size_t alignment_hint, bool exec, | |
2894 const char* mesg) { | |
2895 assert(mesg != NULL, "mesg must be specified"); | |
2896 int err = os::Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec); | |
2897 if (err != 0) { | |
2898 // the caller wants all commit errors to exit with the specified mesg: | |
2899 warn_fail_commit_memory(addr, bytes, alignment_hint, exec, err); | |
2900 vm_exit_out_of_memory(bytes, OOM_MMAP_ERROR, mesg); | |
2901 } | |
2827 } | 2902 } |
2828 | 2903 |
2829 // Uncommit the pages in a specified region. | 2904 // Uncommit the pages in a specified region. |
2830 void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) { | 2905 void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) { |
2831 if (madvise(addr, bytes, MADV_FREE) < 0) { | 2906 if (madvise(addr, bytes, MADV_FREE) < 0) { |
2833 return; | 2908 return; |
2834 } | 2909 } |
2835 } | 2910 } |
2836 | 2911 |
2837 bool os::pd_create_stack_guard_pages(char* addr, size_t size) { | 2912 bool os::pd_create_stack_guard_pages(char* addr, size_t size) { |
2838 return os::commit_memory(addr, size); | 2913 return os::commit_memory(addr, size, !ExecMem); |
2839 } | 2914 } |
2840 | 2915 |
2841 bool os::remove_stack_guard_pages(char* addr, size_t size) { | 2916 bool os::remove_stack_guard_pages(char* addr, size_t size) { |
2842 return os::uncommit_memory(addr, size); | 2917 return os::uncommit_memory(addr, size); |
2843 } | 2918 } |