Skip to content

Commit dc3a9b4

Browse files
authored
Acquire and release Heap_lock on VM_MMTkSTWOperation (#316)
This PR changes how we acquire `Heap_lock` for GC. With the changes, we acquire the lock in `VM_MMTkSTWOperation::doit_prologue()`, and release the lock in epilogue. We hold the lock during the entire STW. This is the same behavior as OpenJDK's GCs. We used to acquire the lock during reference enqueueing before `swap_reference_pending_list()` (which requires the lock to be locked), and acquire the lock before notifying the reference handler. This causes deadlock as seen in #315 . The `has_reference_pending_list` call used for an assertion in reference enqueueing is removed, as it requires the current thread to hold the lock which cannot be satisfied. This PR should fix #315.
1 parent db91fd1 commit dc3a9b4

File tree

3 files changed

+15
-12
lines changed

3 files changed

+15
-12
lines changed

openjdk/mmtkUpcalls.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,6 @@ static void mmtk_resume_mutators(void *tls) {
8787
MutexLockerEx locker(MMTkHeap::heap()->gc_lock(), Mutex::_no_safepoint_check_flag);
8888
MMTkHeap::heap()->gc_lock()->notify_all();
8989
}
90-
91-
log_debug(gc)("Notifying mutators blocking on Heap_lock for reference pending list...");
92-
// Note: That's the ReferenceHandler thread.
93-
{
94-
MutexLockerEx x(Heap_lock, Mutex::_no_safepoint_check_flag);
95-
if (Universe::has_reference_pending_list()) {
96-
Heap_lock->notify_all();
97-
}
98-
}
9990
}
10091

10192
static const int GC_THREAD_KIND_WORKER = 1;
@@ -302,8 +293,6 @@ static void mmtk_enqueue_references(void** objects, size_t len) {
302293
return;
303294
}
304295

305-
MutexLocker x(Heap_lock);
306-
307296
oop first = (oop) objects[0]; // This points to the first node of the linked list.
308297
oop last = first; // This points to the last node of the linked list.
309298

@@ -324,7 +313,6 @@ static void mmtk_enqueue_references(void** objects, size_t len) {
324313

325314
oop old_first = Universe::swap_reference_pending_list(first);
326315
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(last, java_lang_ref_Reference::discovered_offset, old_first);
327-
assert(Universe::has_reference_pending_list(), "Reference pending list is empty after swap");
328316
}
329317

330318
OpenJDK_Upcalls mmtk_upcalls = {

openjdk/mmtkVMOperation.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,21 @@ VM_MMTkSTWOperation::VM_MMTkSTWOperation(MMTkVMCompanionThread *companion_thread
3232
_companion_thread(companion_thread) {
3333
}
3434

35+
bool VM_MMTkSTWOperation::doit_prologue() {
36+
Heap_lock->lock();
37+
return true;
38+
}
39+
3540
void VM_MMTkSTWOperation::doit() {
3641
log_trace(vmthread)("Entered VM_MMTkSTWOperation::doit().");
3742
_companion_thread->do_mmtk_stw_operation();
3843
log_trace(vmthread)("Leaving VM_MMTkSTWOperation::doit()");
3944
}
45+
46+
void VM_MMTkSTWOperation::doit_epilogue() {
47+
// Notify the reference processing thread
48+
if (Universe::has_reference_pending_list()) {
49+
Heap_lock->notify_all();
50+
}
51+
Heap_lock->unlock();
52+
}

openjdk/mmtkVMOperation.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ class VM_MMTkSTWOperation : public VM_MMTkOperation {
3939

4040
public:
4141
VM_MMTkSTWOperation(MMTkVMCompanionThread *companion_thread);
42+
virtual bool doit_prologue() override;
4243
virtual void doit() override;
44+
virtual void doit_epilogue() override;
4345
};
4446

4547
#endif // MMTK_OPENJDK_MMTK_VM_OPERATION_HPP

0 commit comments

Comments
 (0)