src/os/solaris/vm/os_solaris.cpp

Print this page



2791 ////////////////////////////////////////////////////////////////////////////////
2792 // Virtual Memory
2793 
2794 static int page_size = -1;
2795 
2796 // The mmap MAP_ALIGN flag is supported on Solaris 9 and later.  init_2() will
2797 // clear this var if support is not available.
2798 static bool has_map_align = true;
2799 
2800 int os::vm_page_size() {
2801   assert(page_size != -1, "must call os::init");
2802   return page_size;
2803 }
2804 
2805 // Solaris allocates memory by pages.
2806 int os::vm_allocation_granularity() {
2807   assert(page_size != -1, "must call os::init");
2808   return page_size;
2809 }
2810 
2811 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {



































2812   int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
2813   size_t size = bytes;
2814   char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot);
2815   if (res != NULL) {
2816     if (UseNUMAInterleaving) {
2817       numa_make_global(addr, bytes);
2818     }
2819     return true;
2820   }
2821   return false;








2822 }
2823 
2824 bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint,
2825                        bool exec) {
2826   if (commit_memory(addr, bytes, exec)) {
















2827     if (UseMPSS && alignment_hint > (size_t)vm_page_size()) {
2828       // If the large page size has been set and the VM
2829       // is using large pages, use the large page size
2830       // if it is smaller than the alignment hint. This is
2831       // a case where the VM wants to use a larger alignment size
2832       // for its own reasons but still want to use large pages
2833       // (which is what matters to setting the mpss range.
2834       size_t page_size = 0;
2835       if (large_page_size() < alignment_hint) {
2836         assert(UseLargePages, "Expected to be here for large page use only");
2837         page_size = large_page_size();
2838       } else {
2839         // If the alignment hint is less than the large page
2840         // size, the VM wants a particular alignment (thus the hint)
2841         // for internal reasons.  Try to set the mpss range using
2842         // the alignment_hint.
2843         page_size = alignment_hint;
2844       }
2845       // Since this is a hint, ignore any failures.
2846       (void)Solaris::set_mpss_range(addr, bytes, page_size);
2847     }
2848     return true;
2849   }
2850   return false;
2851 }
2852 

















2853 // Uncommit the pages in a specified region.
2854 void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) {
2855   if (madvise(addr, bytes, MADV_FREE) < 0) {
2856     debug_only(warning("MADV_FREE failed."));
2857     return;
2858   }
2859 }
2860 
2861 bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
2862   return os::commit_memory(addr, size);
2863 }
2864 
2865 bool os::remove_stack_guard_pages(char* addr, size_t size) {
2866   return os::uncommit_memory(addr, size);
2867 }
2868 
2869 // Change the page size in a given range.
2870 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
2871   assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned.");
2872   assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned.");
2873   if (UseLargePages && UseMPSS) {
2874     Solaris::set_mpss_range(addr, bytes, alignment_hint);
2875   }
2876 }
2877 
2878 // Tell the OS to make the range local to the first-touching LWP
2879 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
2880   assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
2881   if (madvise(addr, bytes, MADV_ACCESS_LWP) < 0) {
2882     debug_only(warning("MADV_ACCESS_LWP failed."));



2791 ////////////////////////////////////////////////////////////////////////////////
2792 // Virtual Memory
2793 
2794 static int page_size = -1;
2795 
2796 // The mmap MAP_ALIGN flag is supported on Solaris 9 and later.  init_2() will
2797 // clear this var if support is not available.
2798 static bool has_map_align = true;
2799 
2800 int os::vm_page_size() {
2801   assert(page_size != -1, "must call os::init");
2802   return page_size;
2803 }
2804 
2805 // Solaris allocates memory by pages.
2806 int os::vm_allocation_granularity() {
2807   assert(page_size != -1, "must call os::init");
2808   return page_size;
2809 }
2810 
2811 static bool recoverable_mmap_error(int err) {
2812   // See if the error is one we can let the caller handle. This
2813   // list of errno values comes from the Solaris mmap(2) man page.
2814   switch (err) {
2815   case EBADF:
2816   case EINVAL:
2817   case ENOTSUP:
2818     // let the caller deal with these errors
2819     return true;
2820 
2821   default:
2822     // Any remaining errors on this OS can cause our reserved mapping
2823     // to be lost. That can cause confusion where different data
2824     // structures think they have the same memory mapped. The worst
2825     // scenario is if both the VM and a library think they have the
2826     // same memory mapped.
2827     return false;
2828   }
2829 }
2830 
2831 static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec,
2832                                     int err) {
2833   warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
2834           ", %d) failed; error='%s' (errno=%d)", addr, bytes, exec,
2835           strerror(err), err);
2836 }
2837 
2838 static void warn_fail_commit_memory(char* addr, size_t bytes,
2839                                     size_t alignment_hint, bool exec,
2840                                     int err) {
2841   warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
2842           ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d)", addr, bytes,
2843           alignment_hint, exec, strerror(err), err);
2844 }
2845 
2846 int os::Solaris::commit_memory_impl(char* addr, size_t bytes, bool exec) {
2847   int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
2848   size_t size = bytes;
2849   char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot);
2850   if (res != NULL) {
2851     if (UseNUMAInterleaving) {
2852       numa_make_global(addr, bytes);
2853     }
2854     return 0;
2855   }
2856 
2857   int err = errno;  // save errno from mmap() call in mmap_chunk()
2858 
2859   if (!recoverable_mmap_error(err)) {
2860     warn_fail_commit_memory(addr, bytes, exec, err);
2861     vm_exit_out_of_memory(bytes, "committing reserved memory.");
2862   }
2863 
2864   return err;
2865 }
2866 
2867 bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
2868   return Solaris::commit_memory_impl(addr, bytes, exec) == 0;
2869 }
2870 
2871 void os::pd_commit_memory_or_exit(char* addr, size_t bytes, bool exec,
2872                                   const char* mesg) {
2873   assert(mesg != NULL, "mesg must be specified");
2874   int err = os::Solaris::commit_memory_impl(addr, bytes, exec);
2875   if (err != 0) {
2876     // the caller wants all commit errors to exit with the specified mesg:
2877     warn_fail_commit_memory(addr, bytes, exec, err);
2878     vm_exit_out_of_memory(bytes, mesg);
2879   }
2880 }
2881 
2882 int os::Solaris::commit_memory_impl(char* addr, size_t bytes,
2883                                     size_t alignment_hint, bool exec) {
2884   int err = Solaris::commit_memory_impl(addr, bytes, exec);
2885   if (err == 0) {
2886     if (UseMPSS && alignment_hint > (size_t)vm_page_size()) {
2887       // If the large page size has been set and the VM
2888       // is using large pages, use the large page size
2889       // if it is smaller than the alignment hint. This is
2890       // a case where the VM wants to use a larger alignment size
2891       // for its own reasons but still want to use large pages
2892       // (which is what matters to setting the mpss range.
2893       size_t page_size = 0;
2894       if (large_page_size() < alignment_hint) {
2895         assert(UseLargePages, "Expected to be here for large page use only");
2896         page_size = large_page_size();
2897       } else {
2898         // If the alignment hint is less than the large page
2899         // size, the VM wants a particular alignment (thus the hint)
2900         // for internal reasons.  Try to set the mpss range using
2901         // the alignment_hint.
2902         page_size = alignment_hint;
2903       }
2904       // Since this is a hint, ignore any failures.
2905       (void)Solaris::set_mpss_range(addr, bytes, page_size);
2906     }

2907   }
2908   return err;
2909 }
2910 
2911 bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint,
2912                           bool exec) {
2913   return Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec) == 0;
2914 }
2915 
2916 void os::pd_commit_memory_or_exit(char* addr, size_t bytes,
2917                                   size_t alignment_hint, bool exec,
2918                                   const char* mesg) {
2919   assert(mesg != NULL, "mesg must be specified");
2920   int err = os::Solaris::commit_memory_impl(addr, bytes, alignment_hint, exec);
2921   if (err != 0) {
2922     // the caller wants all commit errors to exit with the specified mesg:
2923     warn_fail_commit_memory(addr, bytes, alignment_hint, exec, err);
2924     vm_exit_out_of_memory(bytes, mesg);
2925   }
2926 }
2927 
2928 // Uncommit the pages in a specified region.
2929 void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) {
2930   if (madvise(addr, bytes, MADV_FREE) < 0) {
2931     debug_only(warning("MADV_FREE failed."));
2932     return;
2933   }
2934 }
2935 
2936 bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
2937   return os::commit_memory(addr, size, !ExecMem);
2938 }
2939 
2940 bool os::remove_stack_guard_pages(char* addr, size_t size) {
2941   return os::uncommit_memory(addr, size);
2942 }
2943 
2944 // Change the page size in a given range.
2945 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
2946   assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned.");
2947   assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned.");
2948   if (UseLargePages && UseMPSS) {
2949     Solaris::set_mpss_range(addr, bytes, alignment_hint);
2950   }
2951 }
2952 
2953 // Tell the OS to make the range local to the first-touching LWP
2954 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
2955   assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned.");
2956   if (madvise(addr, bytes, MADV_ACCESS_LWP) < 0) {
2957     debug_only(warning("MADV_ACCESS_LWP failed."));