Mercurial > hg > graal-jvmci-8
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() { }