diff src/os/linux/vm/os_linux.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/linux/vm/os_linux.cpp	Tue Apr 01 14:09:03 2014 +0200
+++ b/src/os/linux/vm/os_linux.cpp	Tue Apr 01 13:57:07 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -139,7 +139,7 @@
 
 // For diagnostics to print a message once. see run_periodic_checks
 static sigset_t check_signal_done;
-static bool check_signals = true;
+static bool check_signals = true;;
 
 static pid_t _initial_pid = 0;
 
@@ -257,10 +257,8 @@
 static char cpu_arch[] = "amd64";
 #elif defined(ARM)
 static char cpu_arch[] = "arm";
-#elif defined(PPC32)
+#elif defined(PPC)
 static char cpu_arch[] = "ppc";
-#elif defined(PPC64)
-static char cpu_arch[] = "ppc64";
 #elif defined(SPARC)
 #  ifdef _LP64
 static char cpu_arch[] = "sparcv9";
@@ -532,9 +530,6 @@
   sigaddset(&unblocked_sigs, SIGSEGV);
   sigaddset(&unblocked_sigs, SIGBUS);
   sigaddset(&unblocked_sigs, SIGFPE);
-#if defined(PPC64)
-  sigaddset(&unblocked_sigs, SIGTRAP);
-#endif
   sigaddset(&unblocked_sigs, SR_signum);
 
   if (!ReduceSignalUsage) {
@@ -1456,7 +1451,7 @@
 }
 
 jlong os::javaTimeNanos() {
-  if (os::supports_monotonic_clock()) {
+  if (Linux::supports_monotonic_clock()) {
     struct timespec tp;
     int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);
     assert(status == 0, "gettime error");
@@ -1472,7 +1467,7 @@
 }
 
 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
-  if (os::supports_monotonic_clock()) {
+  if (Linux::supports_monotonic_clock()) {
     info_ptr->max_value = ALL_64_BITS;
 
     // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past
@@ -2109,9 +2104,6 @@
   return res;
 }
 
-void* os::get_default_process_handle() {
-  return (void*)::dlopen(NULL, RTLD_LAZY);
-}
 
 static bool _print_ascii_file(const char* filename, outputStream* st) {
   int fd = ::open(filename, O_RDONLY);
@@ -2265,12 +2257,58 @@
   st->cr();
 }
 
+// Taken from /usr/include/bits/siginfo.h  Supposed to be architecture specific
+// but they're the same for all the linux arch that we support
+// and they're the same for solaris but there's no common place to put this.
+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", "FPE_FLTDEN" };
+
+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));
+  if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) {
+    st->print("si_errno=%s", buf);
+  } 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)) {
@@ -2300,9 +2338,6 @@
   print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen);
   print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
   print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
-#if defined(PPC64)
-  print_signal_handler(st, SIGTRAP, buf, buflen);
-#endif
 }
 
 static char saved_jvm_path[MAXPATHLEN] = {0};
@@ -2333,14 +2368,13 @@
   if (rp == NULL)
     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,9 +2996,7 @@
 
   unsigned char vec[1];
   unsigned imin = 1, imax = pages + 1, imid;
-  int mincore_return_value = 0;
-
-  assert(imin <= imax, "Unexpected page size");
+  int mincore_return_value;
 
   while (imin < imax) {
     imid = (imax + imin) / 2;
@@ -3757,33 +3789,88 @@
   return ::read(fd, buf, nBytes);
 }
 
-//
-// Short sleep, direct OS call.
-//
-// Note: certain versions of Linux CFS scheduler (since 2.6.23) do not guarantee
-// sched_yield(2) will actually give up the CPU:
-//
-//   * Alone on this pariticular CPU, keeps running.
-//   * Before the introduction of "skip_buddy" with "compat_yield" disabled
-//     (pre 2.6.39).
-//
-// So calling this with 0 is an alternative.
-//
-void os::naked_short_sleep(jlong ms) {
-  struct timespec req;
-
-  assert(ms < 1000, "Un-interruptable sleep, short time use only");
-  req.tv_sec = 0;
-  if (ms > 0) {
-    req.tv_nsec = (ms % 1000) * 1000000;
-  }
-  else {
-    req.tv_nsec = 1;
-  }
-
-  nanosleep(&req, NULL);
-
-  return;
+// TODO-FIXME: reconcile Solaris' os::sleep with the linux variation.
+// Solaris uses poll(), linux uses park().
+// Poll() is likely a better choice, assuming that Thread.interrupt()
+// generates a SIGUSRx signal. Note that SIGUSR1 can interfere with
+// SIGSEGV, see 4355769.
+
+int os::sleep(Thread* thread, jlong millis, bool interruptible) {
+  assert(thread == Thread::current(),  "thread consistency check");
+
+  ParkEvent * const slp = thread->_SleepEvent ;
+  slp->reset() ;
+  OrderAccess::fence() ;
+
+  if (interruptible) {
+    jlong prevtime = javaTimeNanos();
+
+    for (;;) {
+      if (os::is_interrupted(thread, true)) {
+        return OS_INTRPT;
+      }
+
+      jlong newtime = javaTimeNanos();
+
+      if (newtime - prevtime < 0) {
+        // time moving backwards, should only happen if no monotonic clock
+        // not a guarantee() because JVM should not abort on kernel/glibc bugs
+        assert(!Linux::supports_monotonic_clock(), "time moving backwards");
+      } else {
+        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
+      }
+
+      if(millis <= 0) {
+        return OS_OK;
+      }
+
+      prevtime = newtime;
+
+      {
+        assert(thread->is_Java_thread(), "sanity check");
+        JavaThread *jt = (JavaThread *) thread;
+        ThreadBlockInVM tbivm(jt);
+        OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);
+
+        jt->set_suspend_equivalent();
+        // cleared by handle_special_suspend_equivalent_condition() or
+        // java_suspend_self() via check_and_wait_while_suspended()
+
+        slp->park(millis);
+
+        // were we externally suspended while we were waiting?
+        jt->check_and_wait_while_suspended();
+      }
+    }
+  } else {
+    OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+    jlong prevtime = javaTimeNanos();
+
+    for (;;) {
+      // It'd be nice to avoid the back-to-back javaTimeNanos() calls on
+      // the 1st iteration ...
+      jlong newtime = javaTimeNanos();
+
+      if (newtime - prevtime < 0) {
+        // time moving backwards, should only happen if no monotonic clock
+        // not a guarantee() because JVM should not abort on kernel/glibc bugs
+        assert(!Linux::supports_monotonic_clock(), "time moving backwards");
+      } else {
+        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
+      }
+
+      if(millis <= 0) break ;
+
+      prevtime = newtime;
+      slp->park(millis);
+    }
+    return OS_OK ;
+  }
+}
+
+int os::naked_sleep() {
+  // %% make the sleep time an integer flag. for now use 1 millisec.
+  return os::sleep(Thread::current(), 1, false);
 }
 
 // Sleep forever; naked call to OS-specific sleep; use with CAUTION
@@ -4109,6 +4196,50 @@
   guarantee(osthread->sr.is_running(), "Must be running!");
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// interrupt support
+
+void os::interrupt(Thread* thread) {
+  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
+    "possibility of dangling Thread pointer");
+
+  OSThread* osthread = thread->osthread();
+
+  if (!osthread->interrupted()) {
+    osthread->set_interrupted(true);
+    // More than one thread can get here with the same value of osthread,
+    // resulting in multiple notifications.  We do, however, want the store
+    // to interrupted() to be visible to other threads before we execute unpark().
+    OrderAccess::fence();
+    ParkEvent * const slp = thread->_SleepEvent ;
+    if (slp != NULL) slp->unpark() ;
+  }
+
+  // For JSR166. Unpark even if interrupt status already was set
+  if (thread->is_Java_thread())
+    ((JavaThread*)thread)->parker()->unpark();
+
+  ParkEvent * ev = thread->_ParkEvent ;
+  if (ev != NULL) ev->unpark() ;
+
+}
+
+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 interrupted = osthread->interrupted();
+
+  if (interrupted && clear_interrupted) {
+    osthread->set_interrupted(false);
+    // consider thread->_SleepEvent->reset() ... optional optimization
+  }
+
+  return interrupted;
+}
+
 ///////////////////////////////////////////////////////////////////////////////////
 // signal handling (except suspend/resume)
 
@@ -4336,9 +4467,6 @@
     set_signal_handler(SIGBUS, true);
     set_signal_handler(SIGILL, true);
     set_signal_handler(SIGFPE, true);
-#if defined(PPC64)
-    set_signal_handler(SIGTRAP, true);
-#endif
     set_signal_handler(SIGXFSZ, true);
 
     if (libjsig_is_loaded) {
@@ -4432,8 +4560,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?
@@ -4442,8 +4569,7 @@
     sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK;
   }
 
-  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, (sa_sigaction_t)signalHandler) ||
@@ -4481,9 +4607,7 @@
   DO_SIGNAL_CHECK(SIGBUS);
   DO_SIGNAL_CHECK(SIGPIPE);
   DO_SIGNAL_CHECK(SIGXFSZ);
-#if defined(PPC64)
-  DO_SIGNAL_CHECK(SIGTRAP);
-#endif
+
 
   // ReduceSignalUsage allows the user to override these handlers
   // see comments at the very top and jvm_solaris.h
@@ -4633,7 +4757,7 @@
     fatal(err_msg("pthread_condattr_init: %s", strerror(status)));
   }
   // Only set the clock if CLOCK_MONOTONIC is available
-  if (os::supports_monotonic_clock()) {
+  if (Linux::supports_monotonic_clock()) {
     if ((status = pthread_condattr_setclock(_condattr, CLOCK_MONOTONIC)) != 0) {
       if (status == EINVAL) {
         warning("Unable to use monotonic clock with relative timed-waits" \
@@ -4805,7 +4929,7 @@
     // the future if the appropriate cleanup code can be added to the
     // VM_Exit VMOperation's doit method.
     if (atexit(perfMemory_exit_helper) != 0) {
-      warning("os::init_2 atexit(perfMemory_exit_helper) failed");
+      warning("os::init2 atexit(perfMemory_exit_helper) failed");
     }
   }
 
@@ -4816,7 +4940,8 @@
 }
 
 // this is called at the end of vm_initialization
-void os::init_3(void) {
+void os::init_3(void)
+{
 #ifdef JAVASE_EMBEDDED
   // Start the MemNotifyThread
   if (LowMemoryProtection) {
@@ -5463,7 +5588,7 @@
     seconds = 50000000;
   }
 
-  if (os::supports_monotonic_clock()) {
+  if (os::Linux::supports_monotonic_clock()) {
     struct timespec now;
     int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now);
     assert_status(status == 0, status, "clock_gettime");
@@ -5680,7 +5805,7 @@
   assert (time > 0, "convertTime");
   time_t max_secs = 0;
 
-  if (!os::supports_monotonic_clock() || isAbsolute) {
+  if (!os::Linux::supports_monotonic_clock() || isAbsolute) {
     struct timeval now;
     int status = gettimeofday(&now, NULL);
     assert(status == 0, "gettimeofday");