mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 06:14:49 +02:00
6546236: Thread interrupt() of Thread.sleep() can be lost on Solaris due to race with signal handler
Reviewed-by: dholmes, dcubed
This commit is contained in:
parent
a9868648e6
commit
eff08434da
13 changed files with 180 additions and 467 deletions
|
@ -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 @@ void os::Bsd::clock_init() {
|
|||
|
||||
|
||||
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 @@ jlong os::javaTimeNanos() {
|
|||
}
|
||||
|
||||
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 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) {
|
|||
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 @@ static void do_resume(OSThread* osthread) {
|
|||
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)
|
||||
|
||||
|
|
|
@ -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 @@ class Bsd {
|
|||
// 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;
|
||||
}
|
||||
|
|
|
@ -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 @@ inline int os::set_sock_opt(int fd, int level, int optname,
|
|||
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
|
||||
|
|
|
@ -1451,7 +1451,7 @@ void os::Linux::fast_thread_clock_init() {
|
|||
}
|
||||
|
||||
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 @@ jlong os::javaTimeNanos() {
|
|||
}
|
||||
|
||||
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 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) {
|
|||
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 @@ static void do_resume(OSThread* osthread) {
|
|||
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 @@ void os::init(void) {
|
|||
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 @@ static struct timespec* compute_abstime(timespec* abstime, jlong millis) {
|
|||
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 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
|
|||
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");
|
||||
|
|
|
@ -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 @@ class Linux {
|
|||
// 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;
|
||||
}
|
||||
|
|
|
@ -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 @@ inline int os::set_sock_opt(int fd, int level, int optname,
|
|||
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
|
||||
|
|
|
@ -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 @@ char* os::build_agent_function_name(const char *sym_name, const char *lib_name,
|
|||
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");
|
||||
}
|
||||
|
|
|
@ -332,12 +332,6 @@ void os::Solaris::setup_interruptible(JavaThread* thread) {
|
|||
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 @@ bool os::can_execute_large_page_memory() {
|
|||
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 @@ size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
|
|||
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 @@ void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
|
|||
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() {
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ inline int os::set_sock_opt(int fd, int level, int optname,
|
|||
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
|
||||
|
|
|
@ -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 @@ void os::free_thread(OSThread* osthread) {
|
|||
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 as_long(LARGE_INTEGER x) {
|
|||
|
||||
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_counter() {
|
|||
|
||||
|
||||
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 @@ bool os::bind_to_processor(uint processor_id) {
|
|||
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::javaTimeMillis() {
|
|||
}
|
||||
|
||||
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 @@ jlong os::javaTimeNanos() {
|
|||
}
|
||||
|
||||
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_nt = false;
|
|||
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);
|
||||
|
|
|
@ -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 @@ class win32 {
|
|||
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 @@ class win32 {
|
|||
// 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:
|
||||
|
||||
|
|
|
@ -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 @@ inline int os::close(int fd) {
|
|||
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)
|
||||
|
|
|
@ -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 @@ class os: AllStatic {
|
|||
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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue