8223056: Remove Type-Stable-Memory support for Parkers
Reviewed-by: coleenp, rehn
This commit is contained in:
parent
35c9da7031
commit
77a4302309
src/hotspot
os
share
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -1533,15 +1533,22 @@ void os::PlatformEvent::unpark() {
|
||||
|
||||
// JSR166 support
|
||||
|
||||
os::PlatformParker::PlatformParker() {
|
||||
int status;
|
||||
status = pthread_cond_init(&_cond[REL_INDEX], _condAttr);
|
||||
os::PlatformParker::PlatformParker() : _counter(0), _cur_index(-1) {
|
||||
int status = pthread_cond_init(&_cond[REL_INDEX], _condAttr);
|
||||
assert_status(status == 0, status, "cond_init rel");
|
||||
status = pthread_cond_init(&_cond[ABS_INDEX], NULL);
|
||||
assert_status(status == 0, status, "cond_init abs");
|
||||
status = pthread_mutex_init(_mutex, _mutexAttr);
|
||||
assert_status(status == 0, status, "mutex_init");
|
||||
_cur_index = -1; // mark as unused
|
||||
}
|
||||
|
||||
os::PlatformParker::~PlatformParker() {
|
||||
int status = pthread_cond_destroy(&_cond[REL_INDEX]);
|
||||
assert_status(status == 0, status, "cond_destroy rel");
|
||||
status = pthread_cond_destroy(&_cond[ABS_INDEX]);
|
||||
assert_status(status == 0, status, "cond_destroy abs");
|
||||
status = pthread_mutex_destroy(_mutex);
|
||||
assert_status(status == 0, status, "mutex_destroy");
|
||||
}
|
||||
|
||||
// Parker::park decrements count if > 0, else does a condvar wait. Unpark
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -184,21 +184,21 @@ class PlatformEvent : public CHeapObj<mtSynchronizer> {
|
||||
// API updates of course). But Parker methods use fastpaths that break that
|
||||
// level of encapsulation - so combining the two remains a future project.
|
||||
|
||||
class PlatformParker : public CHeapObj<mtSynchronizer> {
|
||||
class PlatformParker {
|
||||
NONCOPYABLE(PlatformParker);
|
||||
protected:
|
||||
enum {
|
||||
REL_INDEX = 0,
|
||||
ABS_INDEX = 1
|
||||
};
|
||||
volatile int _counter;
|
||||
int _cur_index; // which cond is in use: -1, 0, 1
|
||||
pthread_mutex_t _mutex[1];
|
||||
pthread_cond_t _cond[2]; // one for relative times and one for absolute
|
||||
|
||||
public: // TODO-FIXME: make dtor private
|
||||
~PlatformParker() { guarantee(false, "invariant"); }
|
||||
|
||||
public:
|
||||
PlatformParker();
|
||||
~PlatformParker();
|
||||
};
|
||||
|
||||
// Workaround for a bug in macOSX kernel's pthread support (fixed in Mojave?).
|
||||
|
@ -5431,11 +5431,10 @@ void os::PlatformEvent::unpark() {
|
||||
|
||||
// The Windows implementation of Park is very straightforward: Basic
|
||||
// operations on Win32 Events turn out to have the right semantics to
|
||||
// use them directly. We opportunistically resuse the event inherited
|
||||
// from Monitor.
|
||||
// use them directly.
|
||||
|
||||
void Parker::park(bool isAbsolute, jlong time) {
|
||||
guarantee(_ParkEvent != NULL, "invariant");
|
||||
guarantee(_ParkHandle != NULL, "invariant");
|
||||
// First, demultiplex/decode time arguments
|
||||
if (time < 0) { // don't wait
|
||||
return;
|
||||
@ -5457,16 +5456,16 @@ void Parker::park(bool isAbsolute, jlong time) {
|
||||
|
||||
// Don't wait if interrupted or already triggered
|
||||
if (thread->is_interrupted(false) ||
|
||||
WaitForSingleObject(_ParkEvent, 0) == WAIT_OBJECT_0) {
|
||||
ResetEvent(_ParkEvent);
|
||||
WaitForSingleObject(_ParkHandle, 0) == WAIT_OBJECT_0) {
|
||||
ResetEvent(_ParkHandle);
|
||||
return;
|
||||
} else {
|
||||
ThreadBlockInVM tbivm(thread);
|
||||
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
|
||||
thread->set_suspend_equivalent();
|
||||
|
||||
WaitForSingleObject(_ParkEvent, time);
|
||||
ResetEvent(_ParkEvent);
|
||||
WaitForSingleObject(_ParkHandle, time);
|
||||
ResetEvent(_ParkHandle);
|
||||
|
||||
// If externally suspended while waiting, re-suspend
|
||||
if (thread->handle_special_suspend_equivalent_condition()) {
|
||||
@ -5476,8 +5475,8 @@ void Parker::park(bool isAbsolute, jlong time) {
|
||||
}
|
||||
|
||||
void Parker::unpark() {
|
||||
guarantee(_ParkEvent != NULL, "invariant");
|
||||
SetEvent(_ParkEvent);
|
||||
guarantee(_ParkHandle != NULL, "invariant");
|
||||
SetEvent(_ParkHandle);
|
||||
}
|
||||
|
||||
// Platform Monitor implementation
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -188,18 +188,21 @@ class PlatformEvent : public CHeapObj<mtSynchronizer> {
|
||||
|
||||
|
||||
|
||||
class PlatformParker : public CHeapObj<mtSynchronizer> {
|
||||
protected:
|
||||
HANDLE _ParkEvent ;
|
||||
class PlatformParker {
|
||||
NONCOPYABLE(PlatformParker);
|
||||
|
||||
public:
|
||||
~PlatformParker () { guarantee (0, "invariant") ; }
|
||||
PlatformParker () {
|
||||
_ParkEvent = CreateEvent (NULL, true, false, NULL) ;
|
||||
guarantee (_ParkEvent != NULL, "invariant") ;
|
||||
}
|
||||
protected:
|
||||
HANDLE _ParkHandle;
|
||||
|
||||
} ;
|
||||
public:
|
||||
PlatformParker() {
|
||||
_ParkHandle = CreateEvent (NULL, true, false, NULL) ;
|
||||
guarantee(_ParkHandle != NULL, "invariant") ;
|
||||
}
|
||||
~PlatformParker() {
|
||||
CloseHandle(_ParkHandle);
|
||||
}
|
||||
};
|
||||
|
||||
// Platform specific implementations that underpin VM Mutex/Monitor classes.
|
||||
// Note that CRITICAL_SECTION supports recursive locking, while the semantics
|
||||
|
@ -1001,8 +1001,6 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute,
|
||||
} UNSAFE_END
|
||||
|
||||
UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) {
|
||||
Parker* p = NULL;
|
||||
|
||||
if (jthread != NULL) {
|
||||
ThreadsListHandle tlh;
|
||||
JavaThread* thr = NULL;
|
||||
@ -1012,18 +1010,13 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
|
||||
// This is a valid oop.
|
||||
if (thr != NULL) {
|
||||
// The JavaThread is alive.
|
||||
p = thr->parker();
|
||||
Parker* p = thr->parker();
|
||||
HOTSPOT_THREAD_UNPARK((uintptr_t) p);
|
||||
p->unpark();
|
||||
}
|
||||
}
|
||||
} // ThreadsListHandle is destroyed here.
|
||||
|
||||
// 'p' points to type-stable-memory if non-NULL. If the target
|
||||
// thread terminates before we get here the new user of this
|
||||
// Parker will get a 'spurious' unpark - which is perfectly valid.
|
||||
if (p != NULL) {
|
||||
HOTSPOT_THREAD_UNPARK((uintptr_t) p);
|
||||
p->unpark();
|
||||
}
|
||||
} UNSAFE_END
|
||||
|
||||
UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem)) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -112,55 +112,3 @@ void ParkEvent::operator delete (void * a) {
|
||||
// ParkEvents are type-stable and immortal ...
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
|
||||
// 6399321 As a temporary measure we copied & modified the ParkEvent::
|
||||
// allocate() and release() code for use by Parkers. The Parker:: forms
|
||||
// will eventually be removed as we consolidate and shift over to ParkEvents
|
||||
// for both builtin synchronization and JSR166 operations.
|
||||
|
||||
volatile int Parker::ListLock = 0 ;
|
||||
Parker * volatile Parker::FreeList = NULL ;
|
||||
|
||||
Parker * Parker::Allocate (JavaThread * t) {
|
||||
guarantee (t != NULL, "invariant") ;
|
||||
Parker * p ;
|
||||
|
||||
// Start by trying to recycle an existing but unassociated
|
||||
// Parker from the global free list.
|
||||
// 8028280: using concurrent free list without memory management can leak
|
||||
// pretty badly it turns out.
|
||||
Thread::SpinAcquire(&ListLock, "ParkerFreeListAllocate");
|
||||
{
|
||||
p = FreeList;
|
||||
if (p != NULL) {
|
||||
FreeList = p->FreeNext;
|
||||
}
|
||||
}
|
||||
Thread::SpinRelease(&ListLock);
|
||||
|
||||
if (p != NULL) {
|
||||
guarantee (p->AssociatedWith == NULL, "invariant") ;
|
||||
} else {
|
||||
// Do this the hard way -- materialize a new Parker..
|
||||
p = new Parker() ;
|
||||
}
|
||||
p->AssociatedWith = t ; // Associate p with t
|
||||
p->FreeNext = NULL ;
|
||||
return p ;
|
||||
}
|
||||
|
||||
|
||||
void Parker::Release (Parker * p) {
|
||||
if (p == NULL) return ;
|
||||
guarantee (p->AssociatedWith != NULL, "invariant") ;
|
||||
guarantee (p->FreeNext == NULL , "invariant") ;
|
||||
p->AssociatedWith = NULL ;
|
||||
|
||||
Thread::SpinAcquire(&ListLock, "ParkerFreeListRelease");
|
||||
{
|
||||
p->FreeNext = FreeList;
|
||||
FreeList = p;
|
||||
}
|
||||
Thread::SpinRelease(&ListLock);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, 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
|
||||
@ -27,17 +27,21 @@
|
||||
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
/*
|
||||
* Per-thread blocking support for JSR166. See the Java-level
|
||||
* Documentation for rationale. Basically, park acts like wait, unpark
|
||||
* documentation for rationale. Basically, park acts like wait, unpark
|
||||
* like notify.
|
||||
*
|
||||
* 6271289 --
|
||||
* To avoid errors where an os thread expires but the JavaThread still
|
||||
* exists, Parkers are immortal (type-stable) and are recycled across
|
||||
* new threads. This parallels the ParkEvent implementation.
|
||||
* Because park-unpark allow spurious wakeups it is harmless if an
|
||||
* unpark call unparks a new thread using the old Parker reference.
|
||||
* Parkers are inherently part of their associated JavaThread and are only
|
||||
* accessed when the JavaThread is guaranteed to be alive (e.g. by operating
|
||||
* on the current thread, or by having the thread protected by a
|
||||
* ThreadsListHandle.
|
||||
*
|
||||
* Class Parker is declared in shared code and extends the platform-specific
|
||||
* os::PlatformParker class, which contains the actual implementation
|
||||
* mechanics (condvars/events etc). The implementation for park() and unpark()
|
||||
* are also in the platform-specific os_<os>.cpp files.
|
||||
*
|
||||
* In the future we'll want to think about eliminating Parker and using
|
||||
* ParkEvent instead. There's considerable duplication between the two
|
||||
@ -46,32 +50,15 @@
|
||||
*/
|
||||
|
||||
class Parker : public os::PlatformParker {
|
||||
private:
|
||||
volatile int _counter ;
|
||||
Parker * FreeNext ;
|
||||
JavaThread * AssociatedWith ; // Current association
|
||||
private:
|
||||
NONCOPYABLE(Parker);
|
||||
public:
|
||||
Parker() : PlatformParker() {}
|
||||
|
||||
public:
|
||||
Parker() : PlatformParker() {
|
||||
_counter = 0 ;
|
||||
FreeNext = NULL ;
|
||||
AssociatedWith = NULL ;
|
||||
}
|
||||
protected:
|
||||
~Parker() { ShouldNotReachHere(); }
|
||||
public:
|
||||
// For simplicity of interface with Java, all forms of park (indefinite,
|
||||
// relative, and absolute) are multiplexed into one call.
|
||||
void park(bool isAbsolute, jlong time);
|
||||
void unpark();
|
||||
|
||||
// Lifecycle operators
|
||||
static Parker * Allocate (JavaThread * t) ;
|
||||
static void Release (Parker * e) ;
|
||||
private:
|
||||
static Parker * volatile FreeList ;
|
||||
static volatile int ListLock ;
|
||||
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
@ -1565,7 +1565,7 @@ JavaThread::JavaThread() :
|
||||
_should_post_on_exceptions_flag(JNI_FALSE),
|
||||
_thread_stat(new ThreadStatistics()),
|
||||
|
||||
_parker(Parker::Allocate(this)),
|
||||
_parker(),
|
||||
_cached_monitor_info(nullptr),
|
||||
|
||||
_class_to_be_initialized(nullptr),
|
||||
@ -1603,6 +1603,9 @@ JavaThread::JavaThread(bool is_attaching_via_jni) : JavaThread() {
|
||||
// interrupt support
|
||||
|
||||
void JavaThread::interrupt() {
|
||||
// All callers should have 'this' thread protected by a
|
||||
// ThreadsListHandle so that it cannot terminate and deallocate
|
||||
// itself.
|
||||
debug_only(check_for_dangling_thread_pointer(this);)
|
||||
|
||||
// For Windows _interrupt_event
|
||||
@ -1700,10 +1703,6 @@ JavaThread::~JavaThread() {
|
||||
// Ask ServiceThread to release the threadObj OopHandle
|
||||
ServiceThread::add_oop_handle_release(_threadObj);
|
||||
|
||||
// JSR166 -- return the parker to the free list
|
||||
Parker::Release(_parker);
|
||||
_parker = NULL;
|
||||
|
||||
// Return the sleep event to the free list
|
||||
ParkEvent::Release(_SleepEvent);
|
||||
_SleepEvent = NULL;
|
||||
|
@ -66,8 +66,6 @@ class JvmtiThreadState;
|
||||
class JvmtiVMObjectAllocEventCollector;
|
||||
class ThreadStatistics;
|
||||
class ConcurrentLocksDump;
|
||||
class ParkEvent;
|
||||
class Parker;
|
||||
class MonitorInfo;
|
||||
|
||||
class BufferBlob;
|
||||
@ -1854,9 +1852,9 @@ class JavaThread: public Thread {
|
||||
|
||||
// JSR166 per-thread parker
|
||||
private:
|
||||
Parker* _parker;
|
||||
Parker _parker;
|
||||
public:
|
||||
Parker* parker() { return _parker; }
|
||||
Parker* parker() { return &_parker; }
|
||||
|
||||
// Biased locking support
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user