Mercurial > hg > graal-jvmci-8
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");