8180599: Possibly miss to iterate monitors on thread exit
Move thread-local monitors to global lists before thread is removed from global threads list, to ensure all monitors get scanned Reviewed-by: dholmes, rehn
This commit is contained in:
parent
4e05c8c099
commit
8bda8fc602
@ -1283,14 +1283,14 @@ void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
|
|||||||
// a global gOmInUseList under the global list lock so these
|
// a global gOmInUseList under the global list lock so these
|
||||||
// will continue to be scanned.
|
// will continue to be scanned.
|
||||||
//
|
//
|
||||||
// We currently call omFlush() from the Thread:: dtor _after the thread
|
// We currently call omFlush() from Threads::remove() _before the thread
|
||||||
// has been excised from the thread list and is no longer a mutator.
|
// has been excised from the thread list and is no longer a mutator.
|
||||||
// That means that omFlush() can run concurrently with a safepoint and
|
// This means that omFlush() can not run concurrently with a safepoint and
|
||||||
// the scavenge operator. Calling omFlush() from JavaThread::exit() might
|
// interleave with the scavenge operator. In particular, this ensures that
|
||||||
// be a better choice as we could safely reason that that the JVM is
|
// the thread's monitors are scanned by a GC safepoint, either via
|
||||||
// not at a safepoint at the time of the call, and thus there could
|
// Thread::oops_do() (if safepoint happens before omFlush()) or via
|
||||||
// be not inopportune interleavings between omFlush() and the scavenge
|
// ObjectSynchronizer::oops_do() (if it happens after omFlush() and the thread's
|
||||||
// operator.
|
// monitors have been transferred to the global in-use list).
|
||||||
|
|
||||||
void ObjectSynchronizer::omFlush(Thread * Self) {
|
void ObjectSynchronizer::omFlush(Thread * Self) {
|
||||||
ObjectMonitor * list = Self->omFreeList; // Null-terminated SLL
|
ObjectMonitor * list = Self->omFreeList; // Null-terminated SLL
|
||||||
@ -1338,6 +1338,8 @@ void ObjectSynchronizer::omFlush(Thread * Self) {
|
|||||||
tail->FreeNext = gFreeList;
|
tail->FreeNext = gFreeList;
|
||||||
gFreeList = list;
|
gFreeList = list;
|
||||||
gMonitorFreeCount += tally;
|
gMonitorFreeCount += tally;
|
||||||
|
assert(Self->omFreeCount == tally, "free-count off");
|
||||||
|
Self->omFreeCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inUseTail != NULL) {
|
if (inUseTail != NULL) {
|
||||||
|
@ -336,9 +336,6 @@ void Thread::record_stack_base_and_size() {
|
|||||||
|
|
||||||
|
|
||||||
Thread::~Thread() {
|
Thread::~Thread() {
|
||||||
// Reclaim the objectmonitors from the omFreeList of the moribund thread.
|
|
||||||
ObjectSynchronizer::omFlush(this);
|
|
||||||
|
|
||||||
EVENT_THREAD_DESTRUCT(this);
|
EVENT_THREAD_DESTRUCT(this);
|
||||||
|
|
||||||
// stack_base can be NULL if the thread is never started or exited before
|
// stack_base can be NULL if the thread is never started or exited before
|
||||||
@ -4251,6 +4248,10 @@ void Threads::add(JavaThread* p, bool force_daemon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Threads::remove(JavaThread* p) {
|
void Threads::remove(JavaThread* p) {
|
||||||
|
|
||||||
|
// Reclaim the objectmonitors from the omInUseList and omFreeList of the moribund thread.
|
||||||
|
ObjectSynchronizer::omFlush(p);
|
||||||
|
|
||||||
// Extra scope needed for Thread_lock, so we can check
|
// Extra scope needed for Thread_lock, so we can check
|
||||||
// that we do not remove thread without safepoint code notice
|
// that we do not remove thread without safepoint code notice
|
||||||
{ MutexLocker ml(Threads_lock);
|
{ MutexLocker ml(Threads_lock);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user