8230423: Move os::sleep to JavaThread::sleep
Reviewed-by: rehn, dcubed
This commit is contained in:
parent
091cf3608b
commit
99252bd9d6
src/hotspot
cpu/x86
os
share
gc/shenandoah
jvmci
prims
runtime
test/hotspot/gtest
@ -62,7 +62,7 @@ static void do_time_measurements(volatile jlong& time_base,
|
||||
fstart = os::rdtsc();
|
||||
|
||||
// use sleep to prevent compiler from optimizing
|
||||
os::sleep(JavaThread::current(), FT_SLEEP_MILLISECS);
|
||||
JavaThread::current()->sleep(FT_SLEEP_MILLISECS);
|
||||
|
||||
end = os::elapsed_counter();
|
||||
OrderAccess::fence();
|
||||
|
@ -645,7 +645,8 @@ void os::naked_short_sleep(jlong ms) {
|
||||
|
||||
void os::interrupt(Thread* thread) {
|
||||
debug_only(Thread::check_for_dangling_thread_pointer(thread);)
|
||||
|
||||
assert(thread->is_Java_thread(), "invariant");
|
||||
JavaThread* jt = (JavaThread*) thread;
|
||||
OSThread* osthread = thread->osthread();
|
||||
|
||||
if (!osthread->interrupted()) {
|
||||
@ -654,13 +655,12 @@ void os::interrupt(Thread* thread) {
|
||||
// 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 ;
|
||||
ParkEvent * const slp = jt->_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();
|
||||
jt->parker()->unpark();
|
||||
|
||||
ParkEvent * ev = thread->_ParkEvent ;
|
||||
if (ev != NULL) ev->unpark() ;
|
||||
@ -682,7 +682,7 @@ bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
|
||||
// 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
|
||||
// to JavaThread::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) {
|
||||
@ -2049,7 +2049,7 @@ void os::PlatformEvent::unpark() {
|
||||
// shake out uses of park() and unpark() without checking state conditions
|
||||
// properly. This spurious return doesn't manifest itself in any user code
|
||||
// but only in the correctly written condition checking loops of ObjectMonitor,
|
||||
// Mutex/Monitor, Thread::muxAcquire and os::sleep
|
||||
// Mutex/Monitor, Thread::muxAcquire and JavaThread::sleep
|
||||
|
||||
if (Atomic::xchg(1, &_event) >= 0) return;
|
||||
|
||||
|
@ -3595,7 +3595,8 @@ OSReturn os::get_native_priority(const Thread* const thread,
|
||||
|
||||
void os::interrupt(Thread* thread) {
|
||||
debug_only(Thread::check_for_dangling_thread_pointer(thread);)
|
||||
|
||||
assert(thread->is_Java_thread(), "invariant");
|
||||
JavaThread* jt = (JavaThread*) thread;
|
||||
OSThread* osthread = thread->osthread();
|
||||
osthread->set_interrupted(true);
|
||||
// More than one thread can get here with the same value of osthread,
|
||||
@ -3605,14 +3606,12 @@ void os::interrupt(Thread* thread) {
|
||||
OrderAccess::release();
|
||||
SetEvent(osthread->interrupt_event());
|
||||
// For JSR166: unpark after setting status
|
||||
if (thread->is_Java_thread()) {
|
||||
((JavaThread*)thread)->parker()->unpark();
|
||||
}
|
||||
jt->parker()->unpark();
|
||||
|
||||
ParkEvent * ev = thread->_ParkEvent;
|
||||
if (ev != NULL) ev->unpark();
|
||||
|
||||
ev = thread->_SleepEvent;
|
||||
ev = jt->_SleepEvent;
|
||||
if (ev != NULL) ev->unpark();
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ void ShenandoahPacer::pace_for_alloc(size_t words) {
|
||||
}
|
||||
cur = MAX2<size_t>(1, cur);
|
||||
|
||||
os::sleep(JavaThread::current(), cur);
|
||||
JavaThread::current()->sleep(cur);
|
||||
|
||||
double end = os::elapsedTime();
|
||||
total = (size_t)((end - start) * 1000);
|
||||
|
@ -81,7 +81,7 @@ void JVMCICompiler::bootstrap(TRAPS) {
|
||||
do {
|
||||
// Loop until there is something in the queue.
|
||||
do {
|
||||
os::sleep((JavaThread*)THREAD, 100);
|
||||
((JavaThread*)THREAD)->sleep(100);
|
||||
qsize = CompileBroker::queue_size(CompLevel_full_optimization);
|
||||
} while (!_bootstrap_compilation_request_handled && first_round && qsize == 0);
|
||||
first_round = false;
|
||||
|
@ -942,7 +942,7 @@ void JVMCIRuntime::exit_on_pending_exception(JVMCIEnv* JVMCIENV, const char* mes
|
||||
}
|
||||
} else {
|
||||
// Allow error reporting thread to print the stack trace.
|
||||
os::sleep(THREAD, 200);
|
||||
THREAD->sleep(200);
|
||||
}
|
||||
|
||||
before_exit(THREAD);
|
||||
|
@ -2990,7 +2990,7 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
|
||||
} else {
|
||||
ThreadState old_state = thread->osthread()->get_state();
|
||||
thread->osthread()->set_state(SLEEPING);
|
||||
if (os::sleep(thread, millis) == OS_INTRPT) {
|
||||
if (!thread->sleep(millis)) { // interrupted
|
||||
// An asynchronous exception (e.g., ThreadDeathException) could have been thrown on
|
||||
// us while we were sleeping. We do not overwrite those.
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
|
@ -1844,57 +1844,3 @@ void os::naked_sleep(jlong millis) {
|
||||
}
|
||||
naked_short_sleep(millis);
|
||||
}
|
||||
|
||||
int os::sleep(JavaThread* thread, jlong millis) {
|
||||
assert(thread == Thread::current(), "thread consistency check");
|
||||
|
||||
ParkEvent * const slp = thread->_SleepEvent;
|
||||
// Because there can be races with thread interruption sending an unpark()
|
||||
// to the event, we explicitly reset it here to avoid an immediate return.
|
||||
// The actual interrupt state will be checked before we park().
|
||||
slp->reset();
|
||||
// Thread interruption establishes a happens-before ordering in the
|
||||
// Java Memory Model, so we need to ensure we synchronize with the
|
||||
// interrupt state.
|
||||
OrderAccess::fence();
|
||||
|
||||
jlong prevtime = javaTimeNanos();
|
||||
|
||||
for (;;) {
|
||||
// interruption has precedence over timing out
|
||||
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()");
|
||||
} else {
|
||||
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
|
||||
}
|
||||
|
||||
if (millis <= 0) {
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
prevtime = newtime;
|
||||
|
||||
{
|
||||
ThreadBlockInVM tbivm(thread);
|
||||
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
|
||||
|
||||
thread->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?
|
||||
thread->check_and_wait_while_suspended();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -464,8 +464,7 @@ class os: AllStatic {
|
||||
// thread id on Linux/64bit is 64bit, on Windows and Solaris, it's 32bit
|
||||
static intx current_thread_id();
|
||||
static int current_process_id();
|
||||
// Implementation of java.lang.Thread.sleep for JavaThreads
|
||||
static int sleep(JavaThread* thread, jlong ms);
|
||||
|
||||
// Short standalone OS sleep routines suitable for slow path spin loop.
|
||||
// Ignores safepoints/suspension/Thread.interrupt() (so keep it short).
|
||||
// ms/ns = 0, will sleep for the least amount of time allowed by the OS.
|
||||
|
@ -291,7 +291,6 @@ Thread::Thread() {
|
||||
// The stack would act as a cache to avoid calls to ParkEvent::Allocate()
|
||||
// and ::Release()
|
||||
_ParkEvent = ParkEvent::Allocate(this);
|
||||
_SleepEvent = ParkEvent::Allocate(this);
|
||||
_MuxEvent = ParkEvent::Allocate(this);
|
||||
|
||||
#ifdef CHECK_UNHANDLED_OOPS
|
||||
@ -456,7 +455,6 @@ Thread::~Thread() {
|
||||
// It's possible we can encounter a null _ParkEvent, etc., in stillborn threads.
|
||||
// We NULL out the fields for good hygiene.
|
||||
ParkEvent::Release(_ParkEvent); _ParkEvent = NULL;
|
||||
ParkEvent::Release(_SleepEvent); _SleepEvent = NULL;
|
||||
ParkEvent::Release(_MuxEvent); _MuxEvent = NULL;
|
||||
|
||||
delete handle_area();
|
||||
@ -1696,7 +1694,7 @@ void JavaThread::initialize() {
|
||||
_do_not_unlock_if_synchronized = false;
|
||||
_cached_monitor_info = NULL;
|
||||
_parker = Parker::Allocate(this);
|
||||
|
||||
_SleepEvent = ParkEvent::Allocate(this);
|
||||
// Setup safepoint state info for this thread
|
||||
ThreadSafepointState::create(this);
|
||||
|
||||
@ -1808,6 +1806,10 @@ JavaThread::~JavaThread() {
|
||||
Parker::Release(_parker);
|
||||
_parker = NULL;
|
||||
|
||||
// Return the sleep event to the free list
|
||||
ParkEvent::Release(_SleepEvent);
|
||||
_SleepEvent = NULL;
|
||||
|
||||
// Free any remaining previous UnrollBlock
|
||||
vframeArray* old_array = vframe_array_last();
|
||||
|
||||
@ -3339,6 +3341,62 @@ Klass* JavaThread::security_get_caller_class(int depth) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// java.lang.Thread.sleep support
|
||||
// Returns true if sleep time elapsed as expected, and false
|
||||
// if the thread was interrupted.
|
||||
bool JavaThread::sleep(jlong millis) {
|
||||
assert(this == Thread::current(), "thread consistency check");
|
||||
|
||||
ParkEvent * const slp = this->_SleepEvent;
|
||||
// Because there can be races with thread interruption sending an unpark()
|
||||
// to the event, we explicitly reset it here to avoid an immediate return.
|
||||
// The actual interrupt state will be checked before we park().
|
||||
slp->reset();
|
||||
// Thread interruption establishes a happens-before ordering in the
|
||||
// Java Memory Model, so we need to ensure we synchronize with the
|
||||
// interrupt state.
|
||||
OrderAccess::fence();
|
||||
|
||||
jlong prevtime = os::javaTimeNanos();
|
||||
|
||||
for (;;) {
|
||||
// interruption has precedence over timing out
|
||||
if (os::is_interrupted(this, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (millis <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
ThreadBlockInVM tbivm(this);
|
||||
OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */);
|
||||
|
||||
this->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?
|
||||
this->check_and_wait_while_suspended();
|
||||
}
|
||||
|
||||
// Update elapsed time tracking
|
||||
jlong newtime = os::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()");
|
||||
} else {
|
||||
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
|
||||
}
|
||||
prevtime = newtime;
|
||||
}
|
||||
}
|
||||
|
||||
static void compiler_thread_entry(JavaThread* thread, TRAPS) {
|
||||
assert(thread->is_Compiler_thread(), "must be compiler thread");
|
||||
CompileBroker::compiler_thread_loop();
|
||||
|
@ -789,7 +789,6 @@ protected:
|
||||
volatile intptr_t _Stalled;
|
||||
volatile int _TypeTag;
|
||||
ParkEvent * _ParkEvent; // for synchronized()
|
||||
ParkEvent * _SleepEvent; // for Thread.sleep
|
||||
ParkEvent * _MuxEvent; // for low-level muxAcquire-muxRelease
|
||||
int NativeSyncRecursion; // diagnostic
|
||||
|
||||
@ -2055,6 +2054,10 @@ class JavaThread: public Thread {
|
||||
private:
|
||||
InstanceKlass* _class_to_be_initialized;
|
||||
|
||||
// java.lang.Thread.sleep support
|
||||
public:
|
||||
ParkEvent * _SleepEvent;
|
||||
bool sleep(jlong millis);
|
||||
};
|
||||
|
||||
// Inline implementation of JavaThread::current
|
||||
|
@ -145,7 +145,7 @@ TEST_VM(G1FreeIdSetTest, stress) {
|
||||
tty->print_cr("Stressing G1FreeIdSet for %u ms", milliseconds_to_run);
|
||||
{
|
||||
ThreadInVMfromNative invm(this_thread);
|
||||
os::sleep(this_thread, milliseconds_to_run);
|
||||
this_thread->sleep(milliseconds_to_run);
|
||||
}
|
||||
OrderAccess::release_store(&continue_running, false);
|
||||
for (uint i = 0; i < nthreads; ++i) {
|
||||
|
@ -224,7 +224,7 @@ static void run_test(BufferNode::Allocator* allocator, CompletedList* cbl) {
|
||||
tty->print_cr("Stressing allocator for %u ms", milliseconds_to_run);
|
||||
{
|
||||
ThreadInVMfromNative invm(this_thread);
|
||||
os::sleep(this_thread, milliseconds_to_run);
|
||||
this_thread->sleep(milliseconds_to_run);
|
||||
}
|
||||
OrderAccess::release_store(&allocator_running, false);
|
||||
for (uint i = 0; i < nthreads; ++i) {
|
||||
|
@ -136,7 +136,7 @@ TEST_VM(TestSingleWriterSynchronizer, stress) {
|
||||
JavaThread* cur = JavaThread::current();
|
||||
{
|
||||
ThreadInVMfromNative invm(cur);
|
||||
os::sleep(cur, milliseconds_to_run);
|
||||
cur->sleep(milliseconds_to_run);
|
||||
}
|
||||
continue_running = 0;
|
||||
for (uint i = 0; i < nreaders + 1; ++i) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user