src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp

Thu, 13 Jun 2013 11:16:38 -0700

author
dcubed
date
Thu, 13 Jun 2013 11:16:38 -0700
changeset 5255
a837fa3d3f86
parent 3156
f08d439fab8c
child 6461
bdd155477289
permissions
-rw-r--r--

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

     1 /*
     2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "gc_implementation/parallelScavenge/psVirtualspace.hpp"
    27 #include "runtime/os.hpp"
    28 #include "runtime/virtualspace.hpp"
    29 #ifdef TARGET_OS_FAMILY_linux
    30 # include "os_linux.inline.hpp"
    31 #endif
    32 #ifdef TARGET_OS_FAMILY_solaris
    33 # include "os_solaris.inline.hpp"
    34 #endif
    35 #ifdef TARGET_OS_FAMILY_windows
    36 # include "os_windows.inline.hpp"
    37 #endif
    38 #ifdef TARGET_OS_FAMILY_bsd
    39 # include "os_bsd.inline.hpp"
    40 #endif
    42 // PSVirtualSpace
    44 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs, size_t alignment) :
    45   _alignment(alignment)
    46 {
    47   set_reserved(rs);
    48   set_committed(reserved_low_addr(), reserved_low_addr());
    49   DEBUG_ONLY(verify());
    50 }
    52 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs) :
    53   _alignment(os::vm_page_size())
    54 {
    55   set_reserved(rs);
    56   set_committed(reserved_low_addr(), reserved_low_addr());
    57   DEBUG_ONLY(verify());
    58 }
    60 // Deprecated.
    61 PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) {
    62 }
    64 // Deprecated.
    65 bool PSVirtualSpace::initialize(ReservedSpace rs,
    66                                 size_t commit_size) {
    67   set_reserved(rs);
    68   set_committed(reserved_low_addr(), reserved_low_addr());
    70   // Commit to initial size.
    71   assert(commit_size <= rs.size(), "commit_size too big");
    72   bool result = commit_size > 0 ? expand_by(commit_size) : true;
    73   DEBUG_ONLY(verify());
    74   return result;
    75 }
    77 PSVirtualSpace::~PSVirtualSpace() {
    78   release();
    79 }
    81 bool PSVirtualSpace::contains(void* p) const {
    82   char* const cp = (char*)p;
    83   return cp >= committed_low_addr() && cp < committed_high_addr();
    84 }
    86 void PSVirtualSpace::release() {
    87   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
    88   // This may not release memory it didn't reserve.
    89   // Use rs.release() to release the underlying memory instead.
    90   _reserved_low_addr = _reserved_high_addr = NULL;
    91   _committed_low_addr = _committed_high_addr = NULL;
    92   _special = false;
    93 }
    95 bool PSVirtualSpace::expand_by(size_t bytes) {
    96   assert(is_aligned(bytes), "arg not aligned");
    97   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
    99   if (uncommitted_size() < bytes) {
   100     return false;
   101   }
   103   char* const base_addr = committed_high_addr();
   104   bool result = special() ||
   105          os::commit_memory(base_addr, bytes, alignment(), !ExecMem);
   106   if (result) {
   107     _committed_high_addr += bytes;
   108   }
   110   return result;
   111 }
   113 bool PSVirtualSpace::shrink_by(size_t bytes) {
   114   assert(is_aligned(bytes), "arg not aligned");
   115   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
   117   if (committed_size() < bytes) {
   118     return false;
   119   }
   121   char* const base_addr = committed_high_addr() - bytes;
   122   bool result = special() || os::uncommit_memory(base_addr, bytes);
   123   if (result) {
   124     _committed_high_addr -= bytes;
   125   }
   127   return result;
   128 }
   130 size_t
   131 PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) {
   132   assert(is_aligned(bytes), "arg not aligned");
   133   assert(grows_up(), "this space must grow up");
   134   assert(other_space->grows_down(), "other space must grow down");
   135   assert(reserved_high_addr() == other_space->reserved_low_addr(),
   136          "spaces not contiguous");
   137   assert(special() == other_space->special(), "one space is special, the other is not");
   138   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
   139   DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
   141   size_t bytes_needed = bytes;
   143   // First use the uncommitted region in this space.
   144   size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
   145   if (tmp_bytes > 0) {
   146     if (expand_by(tmp_bytes)) {
   147       bytes_needed -= tmp_bytes;
   148     } else {
   149       return 0;
   150     }
   151   }
   153   // Next take from the uncommitted region in the other space, and commit it.
   154   tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
   155   if (tmp_bytes > 0) {
   156     char* const commit_base = committed_high_addr();
   157     if (other_space->special() ||
   158         os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) {
   159       // Reduce the reserved region in the other space.
   160       other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
   161                                 other_space->reserved_high_addr(),
   162                                 other_space->special());
   164       // Grow both reserved and committed in this space.
   165       _reserved_high_addr += tmp_bytes;
   166       _committed_high_addr += tmp_bytes;
   167       bytes_needed -= tmp_bytes;
   168     } else {
   169       return bytes - bytes_needed;
   170     }
   171   }
   173   // Finally take from the already committed region in the other space.
   174   tmp_bytes = bytes_needed;
   175   if (tmp_bytes > 0) {
   176     // Reduce both committed and reserved in the other space.
   177     other_space->set_committed(other_space->committed_low_addr() + tmp_bytes,
   178                                other_space->committed_high_addr());
   179     other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes,
   180                               other_space->reserved_high_addr(),
   181                               other_space->special());
   183     // Grow both reserved and committed in this space.
   184     _reserved_high_addr += tmp_bytes;
   185     _committed_high_addr += tmp_bytes;
   186   }
   188   return bytes;
   189 }
   191 #ifndef PRODUCT
   192 bool PSVirtualSpace::is_aligned(size_t value, size_t align) {
   193   const size_t tmp_value = value + align - 1;
   194   const size_t mask = ~(align - 1);
   195   return (tmp_value & mask) == value;
   196 }
   198 bool PSVirtualSpace::is_aligned(size_t value) const {
   199   return is_aligned(value, alignment());
   200 }
   202 bool PSVirtualSpace::is_aligned(char* value) const {
   203   return is_aligned((size_t)value);
   204 }
   206 void PSVirtualSpace::verify() const {
   207   assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment");
   208   assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr");
   209   assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr");
   210   assert(is_aligned(committed_low_addr()), "bad committed_low_addr");
   211   assert(is_aligned(committed_high_addr()), "bad committed_high_addr");
   213   // Reserved region must be non-empty or both addrs must be 0.
   214   assert(reserved_low_addr() < reserved_high_addr() ||
   215          reserved_low_addr() == NULL && reserved_high_addr() == NULL,
   216          "bad reserved addrs");
   217   assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs");
   219   if (grows_up()) {
   220     assert(reserved_low_addr() == committed_low_addr(), "bad low addrs");
   221     assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs");
   222   } else {
   223     assert(reserved_high_addr() == committed_high_addr(), "bad high addrs");
   224     assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs");
   225   }
   226 }
   228 void PSVirtualSpace::print() const {
   229   gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]:  alignment="
   230                          SIZE_FORMAT "K grows %s%s",
   231                          this, alignment() / K, grows_up() ? "up" : "down",
   232                          special() ? " (pinned in memory)" : "");
   233   gclog_or_tty->print_cr("    reserved=" SIZE_FORMAT "K"
   234                          " [" PTR_FORMAT "," PTR_FORMAT "]"
   235                          " committed=" SIZE_FORMAT "K"
   236                          " [" PTR_FORMAT "," PTR_FORMAT "]",
   237                          reserved_size() / K,
   238                          reserved_low_addr(), reserved_high_addr(),
   239                          committed_size() / K,
   240                          committed_low_addr(), committed_high_addr());
   241 }
   242 #endif // #ifndef PRODUCT
   244 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const {
   245   st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")",
   246                low_boundary(), high(), high_boundary());
   247 }
   249 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs,
   250                                                  size_t alignment) :
   251   PSVirtualSpace(alignment)
   252 {
   253   set_reserved(rs);
   254   set_committed(reserved_high_addr(), reserved_high_addr());
   255   DEBUG_ONLY(verify());
   256 }
   258 PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) {
   259   set_reserved(rs);
   260   set_committed(reserved_high_addr(), reserved_high_addr());
   261   DEBUG_ONLY(verify());
   262 }
   264 bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) {
   265   assert(is_aligned(bytes), "arg not aligned");
   266   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
   268   if (uncommitted_size() < bytes) {
   269     return false;
   270   }
   272   char* const base_addr = committed_low_addr() - bytes;
   273   bool result = special() ||
   274          os::commit_memory(base_addr, bytes, alignment(), !ExecMem);
   275   if (result) {
   276     _committed_low_addr -= bytes;
   277   }
   279   return result;
   280 }
   282 bool PSVirtualSpaceHighToLow::shrink_by(size_t bytes) {
   283   assert(is_aligned(bytes), "arg not aligned");
   284   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
   286   if (committed_size() < bytes) {
   287     return false;
   288   }
   290   char* const base_addr = committed_low_addr();
   291   bool result = special() || os::uncommit_memory(base_addr, bytes);
   292   if (result) {
   293     _committed_low_addr += bytes;
   294   }
   296   return result;
   297 }
   299 size_t PSVirtualSpaceHighToLow::expand_into(PSVirtualSpace* other_space,
   300                                             size_t bytes) {
   301   assert(is_aligned(bytes), "arg not aligned");
   302   assert(grows_down(), "this space must grow down");
   303   assert(other_space->grows_up(), "other space must grow up");
   304   assert(reserved_low_addr() == other_space->reserved_high_addr(),
   305          "spaces not contiguous");
   306   assert(special() == other_space->special(), "one space is special in memory, the other is not");
   307   DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
   308   DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space));
   310   size_t bytes_needed = bytes;
   312   // First use the uncommitted region in this space.
   313   size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed);
   314   if (tmp_bytes > 0) {
   315     if (expand_by(tmp_bytes)) {
   316       bytes_needed -= tmp_bytes;
   317     } else {
   318       return 0;
   319     }
   320   }
   322   // Next take from the uncommitted region in the other space, and commit it.
   323   tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed);
   324   if (tmp_bytes > 0) {
   325     char* const commit_base = committed_low_addr() - tmp_bytes;
   326     if (other_space->special() ||
   327         os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) {
   328       // Reduce the reserved region in the other space.
   329       other_space->set_reserved(other_space->reserved_low_addr(),
   330                                 other_space->reserved_high_addr() - tmp_bytes,
   331                                 other_space->special());
   333       // Grow both reserved and committed in this space.
   334       _reserved_low_addr -= tmp_bytes;
   335       _committed_low_addr -= tmp_bytes;
   336       bytes_needed -= tmp_bytes;
   337     } else {
   338       return bytes - bytes_needed;
   339     }
   340   }
   342   // Finally take from the already committed region in the other space.
   343   tmp_bytes = bytes_needed;
   344   if (tmp_bytes > 0) {
   345     // Reduce both committed and reserved in the other space.
   346     other_space->set_committed(other_space->committed_low_addr(),
   347                                other_space->committed_high_addr() - tmp_bytes);
   348     other_space->set_reserved(other_space->reserved_low_addr(),
   349                               other_space->reserved_high_addr() - tmp_bytes,
   350                               other_space->special());
   352     // Grow both reserved and committed in this space.
   353     _reserved_low_addr -= tmp_bytes;
   354     _committed_low_addr -= tmp_bytes;
   355   }
   357   return bytes;
   358 }
   360 void
   361 PSVirtualSpaceHighToLow::print_space_boundaries_on(outputStream* st) const {
   362   st->print_cr(" (" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]",
   363                high_boundary(), low(), low_boundary());
   364 }

mercurial