diff src/os/solaris/vm/os_solaris.cpp @ 14909:4ca6dc0799b6

Backout jdk9 merge
author Gilles Duboscq <duboscq@ssw.jku.at>
date Tue, 01 Apr 2014 13:57:07 +0200
parents d8041d695d19
children b1911c1e44c8
line wrap: on
line diff
--- a/src/os/solaris/vm/os_solaris.cpp	Tue Apr 01 14:09:03 2014 +0200
+++ b/src/os/solaris/vm/os_solaris.cpp	Tue Apr 01 13:57:07 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -332,6 +332,12 @@
   ThreadStateTransition::transition(thread, thread_state, _thread_blocked);
 }
 
+// Version of setup_interruptible() for threads that are already in
+// _thread_blocked. Used by os_sleep().
+void os::Solaris::setup_interruptible_already_blocked(JavaThread* thread) {
+  thread->frame_anchor()->make_walkable(thread);
+}
+
 JavaThread* os::Solaris::setup_interruptible() {
   JavaThread* thread = (JavaThread*)ThreadLocalStorage::thread();
   setup_interruptible(thread);
@@ -2140,10 +2146,6 @@
   return dlsym(handle, name);
 }
 
-void* os::get_default_process_handle() {
-  return (void*)::dlopen(NULL, RTLD_LAZY);
-}
-
 int os::stat(const char *path, struct stat *sbuf) {
   char pathbuf[MAX_PATH];
   if (strlen(path) > MAX_PATH - 1) {
@@ -2226,8 +2228,8 @@
         st->cr();
         status = true;
       }
+      ::close(fd);
     }
-    ::close(fd);
   }
   return status;
 }
@@ -2245,12 +2247,58 @@
   (void) check_addr0(st);
 }
 
+// Taken from /usr/include/sys/machsig.h  Supposed to be architecture specific
+// but they're the same for all the solaris architectures that we support.
+const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR",
+                          "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG",
+                          "ILL_COPROC", "ILL_BADSTK" };
+
+const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV",
+                          "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES",
+                          "FPE_FLTINV", "FPE_FLTSUB" };
+
+const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" };
+
+const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" };
+
 void os::print_siginfo(outputStream* st, void* siginfo) {
-  const siginfo_t* si = (const siginfo_t*)siginfo;
-
-  os::Posix::print_siginfo_brief(st, si);
-
-  if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) &&
+  st->print("siginfo:");
+
+  const int buflen = 100;
+  char buf[buflen];
+  siginfo_t *si = (siginfo_t*)siginfo;
+  st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen));
+  char *err = strerror(si->si_errno);
+  if (si->si_errno != 0 && err != NULL) {
+    st->print("si_errno=%s", err);
+  } else {
+    st->print("si_errno=%d", si->si_errno);
+  }
+  const int c = si->si_code;
+  assert(c > 0, "unexpected si_code");
+  switch (si->si_signo) {
+  case SIGILL:
+    st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]);
+    st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+    break;
+  case SIGFPE:
+    st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]);
+    st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+    break;
+  case SIGSEGV:
+    st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]);
+    st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+    break;
+  case SIGBUS:
+    st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]);
+    st->print(", si_addr=" PTR_FORMAT, si->si_addr);
+    break;
+  default:
+    st->print(", si_code=%d", si->si_code);
+    // no si_addr
+  }
+
+  if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) &&
       UseSharedSpaces) {
     FileMapInfo* mapinfo = FileMapInfo::current_info();
     if (mapinfo->is_in_shared_space(si->si_addr)) {
@@ -2320,8 +2368,7 @@
     st->print("[%s]", get_signal_handler_name(handler, buf, buflen));
   }
 
-  st->print(", sa_mask[0]=");
-  os::Posix::print_signal_set_short(st, &sa.sa_mask);
+  st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask);
 
   address rh = VMError::get_resetted_sighandler(sig);
   // May be, handler was resetted by VMError?
@@ -2330,8 +2377,7 @@
     sa.sa_flags = VMError::get_resetted_sigflags(sig);
   }
 
-  st->print(", sa_flags=");
-  os::Posix::print_sa_flags(st, sa.sa_flags);
+  st->print(", sa_flags="   PTR32_FORMAT, sa.sa_flags);
 
   // Check: is it our handler?
   if(handler == CAST_FROM_FN_PTR(address, signalHandler) ||
@@ -2391,14 +2437,13 @@
     return;
   }
 
-  if (Arguments::sun_java_launcher_is_altjvm()) {
-    // Support for the java launcher's '-XXaltjvm=<path>' option. Typical
-    // value for buf is "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so".
-    // If "/jre/lib/" appears at the right place in the string, then
-    // assume we are installed in a JDK and we're done.  Otherwise, check
-    // for a JAVA_HOME environment variable and fix up the path so it
-    // looks like libjvm.so is installed there (append a fake suffix
-    // hotspot/libjvm.so).
+  if (Arguments::created_by_gamma_launcher()) {
+    // Support for the gamma launcher.  Typical value for buf is
+    // "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so".  If "/jre/lib/" appears at
+    // the right place in the string, then assume we are installed in a JDK and
+    // we're done.  Otherwise, check for a JAVA_HOME environment variable and fix
+    // up the path so it looks like libjvm.so is installed there (append a
+    // fake suffix hotspot/libjvm.so).
     const char *p = buf + strlen(buf) - 1;
     for (int count = 0; p > buf && count < 5; ++count) {
       for (--p; p > buf && *p != '/'; --p)
@@ -2962,7 +3007,7 @@
 char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) {
   const uint_t info_types[] = { MEMINFO_VLGRP, MEMINFO_VPAGESIZE };
   const size_t types = sizeof(info_types) / sizeof(info_types[0]);
-  uint64_t addrs[MAX_MEMINFO_CNT], outdata[types * MAX_MEMINFO_CNT + 1];
+  uint64_t addrs[MAX_MEMINFO_CNT], outdata[types * MAX_MEMINFO_CNT];
   uint_t validity[MAX_MEMINFO_CNT];
 
   size_t page_size = MAX2((size_t)os::vm_page_size(), page_expected->size);
@@ -3001,7 +3046,7 @@
       }
     }
 
-    if (i < addrs_count) {
+    if (i != addrs_count) {
       if ((validity[i] & 2) != 0) {
         page_found->lgrp_id = outdata[types * i];
       } else {
@@ -3364,6 +3409,61 @@
   return true;
 }
 
+static int os_sleep(jlong millis, bool interruptible) {
+  const jlong limit = INT_MAX;
+  jlong prevtime;
+  int res;
+
+  while (millis > limit) {
+    if ((res = os_sleep(limit, interruptible)) != OS_OK)
+      return res;
+    millis -= limit;
+  }
+
+  // Restart interrupted polls with new parameters until the proper delay
+  // has been completed.
+
+  prevtime = getTimeMillis();
+
+  while (millis > 0) {
+    jlong newtime;
+
+    if (!interruptible) {
+      // Following assert fails for os::yield_all:
+      // assert(!thread->is_Java_thread(), "must not be java thread");
+      res = poll(NULL, 0, millis);
+    } else {
+      JavaThread *jt = JavaThread::current();
+
+      INTERRUPTIBLE_NORESTART_VM_ALWAYS(poll(NULL, 0, millis), res, jt,
+        os::Solaris::clear_interrupted);
+    }
+
+    // INTERRUPTIBLE_NORESTART_VM_ALWAYS returns res == OS_INTRPT for
+    // thread.Interrupt.
+
+    // See c/r 6751923. Poll can return 0 before time
+    // has elapsed if time is set via clock_settime (as NTP does).
+    // res == 0 if poll timed out (see man poll RETURN VALUES)
+    // using the logic below checks that we really did
+    // sleep at least "millis" if not we'll sleep again.
+    if( ( res == 0 ) || ((res == OS_ERR) && (errno == EINTR))) {
+      newtime = getTimeMillis();
+      assert(newtime >= prevtime, "time moving backwards");
+    /* Doing prevtime and newtime in microseconds doesn't help precision,
+       and trying to round up to avoid lost milliseconds can result in a
+       too-short delay. */
+      millis -= newtime - prevtime;
+      if(millis <= 0)
+        return OS_OK;
+      prevtime = newtime;
+    } else
+      return res;
+  }
+
+  return OS_OK;
+}
+
 // Read calls from inside the vm need to perform state transitions
 size_t os::read(int fd, void *buf, unsigned int nBytes) {
   INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
@@ -3373,14 +3473,72 @@
   INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
 }
 
-void os::naked_short_sleep(jlong ms) {
-  assert(ms < 1000, "Un-interruptable sleep, short time use only");
-
-  // usleep is deprecated and removed from POSIX, in favour of nanosleep, but
-  // Solaris requires -lrt for this.
-  usleep((ms * 1000));
-
-  return;
+int os::sleep(Thread* thread, jlong millis, bool interruptible) {
+  assert(thread == Thread::current(),  "thread consistency check");
+
+  // TODO-FIXME: this should be removed.
+  // On Solaris machines (especially 2.5.1) we found that sometimes the VM gets into a live lock
+  // situation with a JavaThread being starved out of a lwp. The kernel doesn't seem to generate
+  // a SIGWAITING signal which would enable the threads library to create a new lwp for the starving
+  // thread. We suspect that because the Watcher thread keeps waking up at periodic intervals the kernel
+  // is fooled into believing that the system is making progress. In the code below we block the
+  // the watcher thread while safepoint is in progress so that it would not appear as though the
+  // system is making progress.
+  if (!Solaris::T2_libthread() &&
+      thread->is_Watcher_thread() && SafepointSynchronize::is_synchronizing() && !Arguments::has_profile()) {
+    // We now try to acquire the threads lock. Since this lock is held by the VM thread during
+    // the entire safepoint, the watcher thread will  line up here during the safepoint.
+    Threads_lock->lock_without_safepoint_check();
+    Threads_lock->unlock();
+  }
+
+  if (thread->is_Java_thread()) {
+    // This is a JavaThread so we honor the _thread_blocked protocol
+    // even for sleeps of 0 milliseconds. This was originally done
+    // as a workaround for bug 4338139. However, now we also do it
+    // to honor the suspend-equivalent protocol.
+
+    JavaThread *jt = (JavaThread *) thread;
+    ThreadBlockInVM tbivm(jt);
+
+    jt->set_suspend_equivalent();
+    // cleared by handle_special_suspend_equivalent_condition() or
+    // java_suspend_self() via check_and_wait_while_suspended()
+
+    int ret_code;
+    if (millis <= 0) {
+      thr_yield();
+      ret_code = 0;
+    } else {
+      // The original sleep() implementation did not create an
+      // OSThreadWaitState helper for sleeps of 0 milliseconds.
+      // I'm preserving that decision for now.
+      OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);
+
+      ret_code = os_sleep(millis, interruptible);
+    }
+
+    // were we externally suspended while we were waiting?
+    jt->check_and_wait_while_suspended();
+
+    return ret_code;
+  }
+
+  // non-JavaThread from this point on:
+
+  if (millis <= 0) {
+    thr_yield();
+    return 0;
+  }
+
+  OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+
+  return os_sleep(millis, interruptible);
+}
+
+int os::naked_sleep() {
+  // %% make the sleep time an integer flag. for now use 1 millisec.
+  return os_sleep(1, false);
 }
 
 // Sleep forever; naked call to OS-specific sleep; use with CAUTION
@@ -4015,6 +4173,68 @@
   errno = old_errno;
 }
 
+
+void os::interrupt(Thread* thread) {
+  assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer");
+
+  OSThread* osthread = thread->osthread();
+
+  int isInterrupted = osthread->interrupted();
+  if (!isInterrupted) {
+      osthread->set_interrupted(true);
+      OrderAccess::fence();
+      // os::sleep() is implemented with either poll (NULL,0,timeout) or
+      // by parking on _SleepEvent.  If the former, thr_kill will unwedge
+      // the sleeper by SIGINTR, otherwise the unpark() will wake the sleeper.
+      ParkEvent * const slp = thread->_SleepEvent ;
+      if (slp != NULL) slp->unpark() ;
+  }
+
+  // For JSR166:  unpark after setting status but before thr_kill -dl
+  if (thread->is_Java_thread()) {
+    ((JavaThread*)thread)->parker()->unpark();
+  }
+
+  // Handle interruptible wait() ...
+  ParkEvent * const ev = thread->_ParkEvent ;
+  if (ev != NULL) ev->unpark() ;
+
+  // When events are used everywhere for os::sleep, then this thr_kill
+  // will only be needed if UseVMInterruptibleIO is true.
+
+  if (!isInterrupted) {
+    int status = thr_kill(osthread->thread_id(), os::Solaris::SIGinterrupt());
+    assert_status(status == 0, status, "thr_kill");
+
+    // Bump thread interruption counter
+    RuntimeService::record_thread_interrupt_signaled_count();
+  }
+}
+
+
+bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
+  assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer");
+
+  OSThread* osthread = thread->osthread();
+
+  bool res = osthread->interrupted();
+
+  // NOTE that since there is no "lock" around these two operations,
+  // there is the possibility that the interrupted flag will be
+  // "false" but that the interrupt event will be set. This is
+  // intentional. The effect of this is that Object.wait() will appear
+  // to have a spurious wakeup, which is not harmful, and the
+  // possibility is so rare that it is not worth the added complexity
+  // to add yet another lock. It has also been recommended not to put
+  // the interrupted flag into the os::Solaris::Event structure,
+  // because it hides the issue.
+  if (res && clear_interrupted) {
+    osthread->set_interrupted(false);
+  }
+  return res;
+}
+
+
 void os::print_statistics() {
 }