RFR: 8212107: VMThread issues and cleanup

Aleksey Shipilev shade at openjdk.java.net
Fri Sep 18 05:36:57 UTC 2020


On Thu, 17 Sep 2020 19:58:02 GMT, Robbin Ehn <rehn at openjdk.org> wrote:

> We simplify the vmThread by removing the queue and refactor the the main loop.
> This solves the issues listed:
> - It can create an extra safepoint directly after a safepoint.
> - It's not safe for a non-JavaThread to add safepoint to queue while GC do oops do.
> - The exposure of the vm operation is dangerous if it's a handshake.
> - The code is a hornets nest with the repetition of checks and branches
> 
> Passes t1-8, and a benchmark run.
> 
> If you want a smaller diff the commits contains the incremental progress and each commit passed t1.

I find juggling the `_next_vm_operation` a bit confusing at the first glance, but that seems superficially okay.

src/hotspot/share/runtime/mutexLocker.cpp line 68:

> 66: Mutex*   TouchedMethodLog_lock        = NULL;
> 67: Mutex*   RetData_lock                 = NULL;
> 68: Monitor* VMOperation_lock        = NULL;

Indenting is a bit off here?

src/hotspot/share/runtime/mutexLocker.hpp line 61:

> 59: extern Mutex*   TouchedMethodLog_lock;           // a lock on allocation of LogExecutedMethods info
> 60: extern Mutex*   RetData_lock;                    // a lock on installation of RetData inside method data
> 61: extern Monitor* VMOperation_lock;           // a lock on queue of vm_operations waiting to execute

Indenting is a bit off?

src/hotspot/share/runtime/thread.hpp line 625:

> 623:
> 624:   // For tracking the heavyweight monitor the thread is pending on.
> 625:   ObjectMonitor* current_pending_monitor() {

If this goes, then the declaration of `_vm_operation_started_count` can also go?

src/hotspot/share/runtime/thread.hpp line 627:

> 625:   ObjectMonitor* current_pending_monitor() {
> 626:     return _current_pending_monitor;
> 627:   }

Ditto for `_vm_operation_completed_count`?

src/hotspot/share/runtime/vmThread.cpp line 222:

> 220: void VMThread::wait_for_vm_thread_exit() {
> 221:   assert(Thread::current()->is_Java_thread(), "Should be a JavaThread");
> 222:   assert(((JavaThread*)Thread::current())->is_terminated(), "Should be terminated");

Looks like just `assert(JavaThread::current()->is_terminated(), "Should be terminated")`.

src/hotspot/share/runtime/vmThread.cpp line 305:

> 303:   // we emit a handshake if it's been more than a second since last.
> 304:   jlong deadline_ms = GuaranteedSafepointInterval != 0 ? GuaranteedSafepointInterval : 1000;
> 305:   deadline_ms += last_halot_ms;

It would seem more straight-forward to write it like this, to highlight the "base" `last_halot_ms` and the "addition"
`interval`:

 // ...
 jlong interval = (GuaranteedSafepointInterval != 0 ? GuaranteedSafepointInterval : 1000);
 jlong deadline_ms = last_halot_ms + interval;
 if (now_ms > deadline_ms) {
    last_halot_ms = now_ms;
    return true;
 }
 return false;

...but that's just a personal preference.

src/hotspot/share/runtime/vmThread.cpp line 313:

> 311: }
> 312:
> 313: void VMThread::cleanup_safepoint_alot() {

This handles `GuaranteedSafepointInterval` periodic op as well, so `cleanup_safepoint_alot` seems misnomer.

src/hotspot/share/runtime/vmThread.hpp line 129:

> 127:   // VM_Operation support
> 128:   static VM_Operation*     _cur_vm_operation;   // Current VM operation
> 129:   static VM_Operation*     _next_vm_operation;

Comment to match `// Current VM operation` above?

src/hotspot/share/runtime/vmThread.cpp line 344:

> 342: }
> 343:
> 344: void VMThread::until_executed(VM_Operation* op) {

...`until_executed`? Feels like missing a verb, e.g. `wait_until_executed`?

src/hotspot/share/runtime/vmThread.cpp line 355:

> 353:     }
> 354:     ml.notify_all();
> 355:     ml.wait();

It is really odd to see back-to-back `notify_all` and `wait`. Would that mean two threads sitting in this loop would
just wake one another continuously?

src/hotspot/share/runtime/vmThread.cpp line 392:

> 390:
> 391:   HandleMark hm(VMThread::vm_thread());
> 392:   EventMark em("Executing %s VM operation: %s", prev_vm_operation ? "nested" : "", op->name());

Check `prev_vm_operation != NULL` explicitly?

src/hotspot/share/runtime/vmThread.cpp line 427:

> 425:
> 426:   // Notify previous op done
> 427:   mu_queue.notify();

So, `notify`, not `notifyAll` here? We sure we want to bet who -- of all current waiters -- gets the notification?

src/hotspot/share/runtime/vmThread.cpp line 470:

> 468:   while (true) {
> 469:     wait_for_operation();
> 470:     if (!should_terminate()) {

This is a trailing block. So it might just be `do { ... } while (!should_terminate())`?

src/hotspot/share/runtime/vmThread.hpp line 103:

> 101:   // Returns the current vm operation if any.
> 102:   static VM_Operation* vm_operation()             {
> 103:     assert(Thread::current()->is_VM_thread(), "Must be);");

Typos in `Must be);`.

-------------

Changes requested by shade (Reviewer).

PR: https://git.openjdk.java.net/jdk/pull/228


More information about the hotspot-dev mailing list