< prev index next >

src/hotspot/os/solaris/os_solaris.cpp

Print this page

        

@@ -1332,19 +1332,12 @@
 
   ::exit(1);
 }
 
 // Die immediately, no exit hook, no abort hook, no cleanup.
-// Dump a core file, if possible, for debugging.
 void os::die() {
-  if (TestUnresponsiveErrorHandler && !CreateCoredumpOnCrash) {
-    // For TimeoutInErrorHandlingTest.java, we just kill the VM
-    // and don't take the time to generate a core file.
-    os::signal_raise(SIGKILL);
-  } else {
-    ::abort();
-  }
+  ::abort(); // dump core (for debugging)
 }
 
 // DLL functions
 
 const char* os::dll_file_extension() { return ".so"; }

@@ -1526,26 +1519,19 @@
 
 void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
   void * result= ::dlopen(filename, RTLD_LAZY);
   if (result != NULL) {
     // Successful loading
-    Events::log(NULL, "Loaded shared library %s", filename);
     return result;
   }
 
   Elf32_Ehdr elf_head;
-  const char* error_report = ::dlerror();
-  if (error_report == NULL) {
-    error_report = "dlerror returned no error description";
-  }
-  if (ebuf != NULL && ebuflen > 0) {
-    ::strncpy(ebuf, error_report, ebuflen-1);
-    ebuf[ebuflen-1]='\0';
-  }
-
-  Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report);
 
+  // Read system error message into ebuf
+  // It may or may not be overwritten below
+  ::strncpy(ebuf, ::dlerror(), ebuflen-1);
+  ebuf[ebuflen-1]='\0';
   int diag_msg_max_length=ebuflen-strlen(ebuf);
   char* diag_msg_buf=ebuf+strlen(ebuf);
 
   if (diag_msg_max_length==0) {
     // No more space in ebuf for additional diagnostics message

@@ -2039,11 +2025,10 @@
 
 void* os::signal(int signal_number, void* handler) {
   struct sigaction sigAct, oldSigAct;
   sigfillset(&(sigAct.sa_mask));
   sigAct.sa_flags = SA_RESTART & ~SA_RESETHAND;
-  sigAct.sa_flags |= SA_SIGINFO;
   sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
 
   if (sigaction(signal_number, &sigAct, &oldSigAct)) {
     // -1 means registration failed
     return (void *)-1;

@@ -2551,30 +2536,128 @@
 
 // Reserve memory at an arbitrary address, only if that area is
 // available (and not reserved for something else).
 
 char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
+  const int max_tries = 10;
+  char* base[max_tries];
+  size_t size[max_tries];
+
+  // Solaris adds a gap between mmap'ed regions.  The size of the gap
+  // is dependent on the requested size and the MMU.  Our initial gap
+  // value here is just a guess and will be corrected later.
+  bool had_top_overlap = false;
+  bool have_adjusted_gap = false;
+  size_t gap = 0x400000;
+
   // Assert only that the size is a multiple of the page size, since
   // that's all that mmap requires, and since that's all we really know
   // about at this low abstraction level.  If we need higher alignment,
   // we can either pass an alignment to this method or verify alignment
   // in one of the methods further up the call chain.  See bug 5044738.
   assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
 
   // Since snv_84, Solaris attempts to honor the address hint - see 5003415.
+  // Give it a try, if the kernel honors the hint we can return immediately.
   char* addr = Solaris::anon_mmap(requested_addr, bytes, 0, false);
 
   volatile int err = errno;
   if (addr == requested_addr) {
     return addr;
+  } else if (addr != NULL) {
+    pd_unmap_memory(addr, bytes);
   }
 
-  if (addr != NULL) {
-    pd_unmap_memory(addr, bytes);
+  if (log_is_enabled(Warning, os)) {
+    char buf[256];
+    buf[0] = '\0';
+    if (addr == NULL) {
+      jio_snprintf(buf, sizeof(buf), ": %s", os::strerror(err));
+    }
+    log_info(os)("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at "
+            PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT
+            "%s", bytes, requested_addr, addr, buf);
+  }
+
+  // Address hint method didn't work.  Fall back to the old method.
+  // In theory, once SNV becomes our oldest supported platform, this
+  // code will no longer be needed.
+  //
+  // Repeatedly allocate blocks until the block is allocated at the
+  // right spot. Give up after max_tries.
+  int i;
+  for (i = 0; i < max_tries; ++i) {
+    base[i] = reserve_memory(bytes);
+
+    if (base[i] != NULL) {
+      // Is this the block we wanted?
+      if (base[i] == requested_addr) {
+        size[i] = bytes;
+        break;
+      }
+
+      // check that the gap value is right
+      if (had_top_overlap && !have_adjusted_gap) {
+        size_t actual_gap = base[i-1] - base[i] - bytes;
+        if (gap != actual_gap) {
+          // adjust the gap value and retry the last 2 allocations
+          assert(i > 0, "gap adjustment code problem");
+          have_adjusted_gap = true;  // adjust the gap only once, just in case
+          gap = actual_gap;
+          log_info(os)("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap);
+          unmap_memory(base[i], bytes);
+          unmap_memory(base[i-1], size[i-1]);
+          i-=2;
+          continue;
+        }
+      }
+
+      // Does this overlap the block we wanted? Give back the overlapped
+      // parts and try again.
+      //
+      // There is still a bug in this code: if top_overlap == bytes,
+      // the overlap is offset from requested region by the value of gap.
+      // In this case giving back the overlapped part will not work,
+      // because we'll give back the entire block at base[i] and
+      // therefore the subsequent allocation will not generate a new gap.
+      // This could be fixed with a new algorithm that used larger
+      // or variable size chunks to find the requested region -
+      // but such a change would introduce additional complications.
+      // It's rare enough that the planets align for this bug,
+      // so we'll just wait for a fix for 6204603/5003415 which
+      // will provide a mmap flag to allow us to avoid this business.
+
+      size_t top_overlap = requested_addr + (bytes + gap) - base[i];
+      if (top_overlap >= 0 && top_overlap < bytes) {
+        had_top_overlap = true;
+        unmap_memory(base[i], top_overlap);
+        base[i] += top_overlap;
+        size[i] = bytes - top_overlap;
+      } else {
+        size_t bottom_overlap = base[i] + bytes - requested_addr;
+        if (bottom_overlap >= 0 && bottom_overlap < bytes) {
+          if (bottom_overlap == 0) {
+            log_info(os)("attempt_reserve_memory_at: possible alignment bug");
+          }
+          unmap_memory(requested_addr, bottom_overlap);
+          size[i] = bytes - bottom_overlap;
+        } else {
+          size[i] = bytes;
+        }
+      }
+    }
   }
 
-  return NULL;
+  // Give back the unused reserved pieces.
+
+  for (int j = 0; j < i; ++j) {
+    if (base[j] != NULL) {
+      unmap_memory(base[j], size[j]);
+    }
+  }
+
+  return (i < max_tries) ? requested_addr : NULL;
 }
 
 bool os::pd_release_memory(char* addr, size_t bytes) {
   size_t size = bytes;
   return munmap(addr, size) == 0;
< prev index next >