# HG changeset patch # User fparain # Date 1392826935 0 # Node ID 6c9332549827c28fac9336357e98c18a1268efec # Parent de7f1b016d55c90f1480f9d8adb3c95046c94c7b 6546236: Thread interrupt() of Thread.sleep() can be lost on Solaris due to race with signal handler Reviewed-by: dholmes, dcubed diff -r de7f1b016d55 -r 6c9332549827 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/bsd/vm/os_bsd.cpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, 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 @@ -994,7 +994,7 @@ jlong os::javaTimeNanos() { - if (Bsd::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { struct timespec tp; int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp); assert(status == 0, "gettime error"); @@ -1010,7 +1010,7 @@ } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { - if (Bsd::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { info_ptr->max_value = ALL_64_BITS; // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past @@ -2559,85 +2559,6 @@ RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes)); } -// TODO-FIXME: reconcile Solaris' os::sleep with the bsd variation. -// Solaris uses poll(), bsd 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(!Bsd::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(!Bsd::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 ; - } -} - void os::naked_short_sleep(jlong ms) { struct timespec req; @@ -3033,50 +2954,6 @@ 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) diff -r de7f1b016d55 -r 6c9332549827 src/os/bsd/vm/os_bsd.hpp --- a/src/os/bsd/vm/os_bsd.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/bsd/vm/os_bsd.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, 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 @@ -131,10 +131,6 @@ // Real-time clock functions static void clock_init(void); - static inline bool supports_monotonic_clock() { - return _clock_gettime != NULL; - } - static int clock_gettime(clockid_t clock_id, struct timespec *tp) { return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; } diff -r de7f1b016d55 -r 6c9332549827 src/os/bsd/vm/os_bsd.inline.hpp --- a/src/os/bsd/vm/os_bsd.inline.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/bsd/vm/os_bsd.inline.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, 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 @@ -286,4 +286,8 @@ return ::setsockopt(fd, level, optname, optval, optlen); } +inline bool os::supports_monotonic_clock() { + return Bsd::_clock_gettime != NULL; +} + #endif // OS_BSD_VM_OS_BSD_INLINE_HPP diff -r de7f1b016d55 -r 6c9332549827 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/linux/vm/os_linux.cpp Wed Feb 19 16:22:15 2014 +0000 @@ -1451,7 +1451,7 @@ } jlong os::javaTimeNanos() { - if (Linux::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { struct timespec tp; int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp); assert(status == 0, "gettime error"); @@ -1467,7 +1467,7 @@ } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { - if (Linux::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { info_ptr->max_value = ALL_64_BITS; // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past @@ -3795,85 +3795,6 @@ return ::read(fd, buf, nBytes); } -// 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 ; - } -} - // // Short sleep, direct OS call. // @@ -4226,50 +4147,6 @@ 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) @@ -4787,7 +4664,7 @@ fatal(err_msg("pthread_condattr_init: %s", strerror(status))); } // Only set the clock if CLOCK_MONOTONIC is available - if (Linux::supports_monotonic_clock()) { + if (os::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" \ @@ -5618,7 +5495,7 @@ seconds = 50000000; } - if (os::Linux::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { struct timespec now; int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); assert_status(status == 0, status, "clock_gettime"); @@ -5835,7 +5712,7 @@ assert (time > 0, "convertTime"); time_t max_secs = 0; - if (!os::Linux::supports_monotonic_clock() || isAbsolute) { + if (!os::supports_monotonic_clock() || isAbsolute) { struct timeval now; int status = gettimeofday(&now, NULL); assert(status == 0, "gettimeofday"); diff -r de7f1b016d55 -r 6c9332549827 src/os/linux/vm/os_linux.hpp --- a/src/os/linux/vm/os_linux.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/linux/vm/os_linux.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, 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 @@ -203,10 +203,6 @@ // fast POSIX clocks support static void fast_thread_clock_init(void); - static inline bool supports_monotonic_clock() { - return _clock_gettime != NULL; - } - static int clock_gettime(clockid_t clock_id, struct timespec *tp) { return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; } diff -r de7f1b016d55 -r 6c9332549827 src/os/linux/vm/os_linux.inline.hpp --- a/src/os/linux/vm/os_linux.inline.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/linux/vm/os_linux.inline.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, 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 @@ -288,4 +288,8 @@ return ::setsockopt(fd, level, optname, optval, optlen); } +inline bool os::supports_monotonic_clock() { + return Linux::_clock_gettime != NULL; +} + #endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP diff -r de7f1b016d55 -r 6c9332549827 src/os/posix/vm/os_posix.cpp --- a/src/os/posix/vm/os_posix.cpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/posix/vm/os_posix.cpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* -* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 1999, 2014, 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 @@ -24,6 +24,7 @@ #include "prims/jvm.h" #include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/vmError.hpp" @@ -307,6 +308,135 @@ return agent_entry_name; } +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(!os::supports_monotonic_clock(), "unexpected time moving backwards detected in os::sleep(interruptible)"); + } 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(!os::supports_monotonic_clock(), "unexpected time moving backwards detected on os::sleep(!interruptible)"); + } else { + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; + } + + if (millis <= 0) break ; + + prevtime = newtime; + slp->park(millis); + } + return OS_OK ; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// 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(); + + // NOTE that since there is no "lock" around the interrupt and + // is_interrupted operations, there is the possibility that the + // interrupted flag (in osThread) will be "false" but that the + // low-level events will be in the signaled state. This is + // intentional. The effect of this is that Object.wait() and + // LockSupport.park() will appear to have a spurious wakeup, which + // is allowed and not harmful, and the possibility is so rare that + // it is not worth the added complexity to add yet another lock. + // For the sleep event an explicit reset is performed on entry + // to os::sleep, so there is no early return. It has also been + // recommended not to put the interrupted flag into the "event" + // structure because it hides the issue. + if (interrupted && clear_interrupted) { + osthread->set_interrupted(false); + // consider thread->_SleepEvent->reset() ... optional optimization + } + + return interrupted; +} + os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); } diff -r de7f1b016d55 -r 6c9332549827 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/solaris/vm/os_solaris.cpp Wed Feb 19 16:22:15 2014 +0000 @@ -332,12 +332,6 @@ 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); @@ -3423,61 +3417,6 @@ 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); @@ -3487,69 +3426,6 @@ INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); } -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); -} - void os::naked_short_sleep(jlong ms) { assert(ms < 1000, "Un-interruptable sleep, short time use only"); @@ -4192,68 +4068,6 @@ 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() { } diff -r de7f1b016d55 -r 6c9332549827 src/os/solaris/vm/os_solaris.inline.hpp --- a/src/os/solaris/vm/os_solaris.inline.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/solaris/vm/os_solaris.inline.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -260,4 +260,10 @@ const char *optval, socklen_t optlen) { return ::setsockopt(fd, level, optname, optval, optlen); } + +inline bool os::supports_monotonic_clock() { + // javaTimeNanos() is monotonic on Solaris, see getTimeNanos() comments + return true; +} + #endif // OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP diff -r de7f1b016d55 -r 6c9332549827 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/windows/vm/os_windows.cpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -628,8 +628,6 @@ delete osthread; } - -static int has_performance_count = 0; static jlong first_filetime; static jlong initial_performance_count; static jlong performance_frequency; @@ -645,7 +643,7 @@ jlong os::elapsed_counter() { LARGE_INTEGER count; - if (has_performance_count) { + if (win32::_has_performance_count) { QueryPerformanceCounter(&count); return as_long(count) - initial_performance_count; } else { @@ -657,7 +655,7 @@ jlong os::elapsed_frequency() { - if (has_performance_count) { + if (win32::_has_performance_count) { return performance_frequency; } else { // the FILETIME time is the number of 100-nanosecond intervals since January 1,1601. @@ -736,15 +734,15 @@ return false; } -static void initialize_performance_counter() { +void os::win32::initialize_performance_counter() { LARGE_INTEGER count; if (QueryPerformanceFrequency(&count)) { - has_performance_count = 1; + win32::_has_performance_count = 1; performance_frequency = as_long(count); QueryPerformanceCounter(&count); initial_performance_count = as_long(count); } else { - has_performance_count = 0; + win32::_has_performance_count = 0; FILETIME wt; GetSystemTimeAsFileTime(&wt); first_filetime = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime); @@ -839,7 +837,7 @@ } jlong os::javaTimeNanos() { - if (!has_performance_count) { + if (!win32::_has_performance_count) { return javaTimeMillis() * NANOSECS_PER_MILLISEC; // the best we can do. } else { LARGE_INTEGER current_count; @@ -852,7 +850,7 @@ } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { - if (!has_performance_count) { + if (!win32::_has_performance_count) { // javaTimeMillis() doesn't have much percision, // but it is not going to wrap -- so all 64 bits info_ptr->max_value = ALL_64_BITS; @@ -3682,6 +3680,8 @@ bool os::win32::_is_windows_2003 = false; bool os::win32::_is_windows_server = false; +bool os::win32::_has_performance_count = 0; + void os::win32::initialize_system_info() { SYSTEM_INFO si; GetSystemInfo(&si); diff -r de7f1b016d55 -r 6c9332549827 src/os/windows/vm/os_windows.hpp --- a/src/os/windows/vm/os_windows.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/windows/vm/os_windows.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -39,6 +39,7 @@ static bool _is_nt; static bool _is_windows_2003; static bool _is_windows_server; + static bool _has_performance_count; static void print_windows_version(outputStream* st); @@ -60,6 +61,9 @@ // load dll from Windows system directory or Windows directory static HINSTANCE load_Windows_dll(const char* name, char *ebuf, int ebuflen); + private: + static void initialize_performance_counter(); + public: // Generic interface: diff -r de7f1b016d55 -r 6c9332549827 src/os/windows/vm/os_windows.inline.hpp --- a/src/os/windows/vm/os_windows.inline.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/os/windows/vm/os_windows.inline.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -107,6 +107,10 @@ return ::close(fd); } +inline bool os::supports_monotonic_clock() { + return win32::_has_performance_count; +} + #ifndef PRODUCT #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \ os::win32::call_test_func_with_wrapper(f) diff -r de7f1b016d55 -r 6c9332549827 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Wed Feb 19 02:58:13 2014 +0000 +++ b/src/share/vm/runtime/os.hpp Wed Feb 19 16:22:15 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -161,6 +161,7 @@ static jlong javaTimeNanos(); static void javaTimeNanos_info(jvmtiTimerInfo *info_ptr); static void run_periodic_checks(); + static bool supports_monotonic_clock(); // Returns the elapsed time in seconds since the vm started.