RFR: 8254758: Change G1ServiceThread to be task based [v5]

Stefan Johansson sjohanss at openjdk.java.net
Mon Nov 2 13:07:30 UTC 2020

On Fri, 30 Oct 2020 11:26:31 GMT, Thomas Schatzl <tschatzl at openjdk.org> wrote:

>> Stefan Johansson has updated the pull request incrementally with four additional commits since the last revision:
>>  - Aditional gtest and assert
>>  - Review tschatzl: Explicit reschedule call in task
>>  - Review tschatzl: Use elapsed_counter
>>  - Review tschatzl: Spelling and such
> src/hotspot/share/gc/g1/g1ServiceThread.cpp line 352:
>> 350:   assert(task != NULL, "not a valid task");
>> 351:   assert(task->next() == NULL, "invariant");
>> 352:   assert(task->time() != DBL_MAX, "invalid time for task");
> s/DBL_MAX/jlong_max ?

Of course, fixed.

> src/hotspot/share/gc/g1/g1ServiceThread.hpp line 105:
>> 103:   // Used both to determine if there are tasks ready to run and
>> 104:   // how long to sleep when nothing is ready.
>> 105:   int64_t time_to_next_task_ms();
> I recommend returning a positive number here because it only raises questions what this means. The implementation of the method also never returns negative values.

The reason for using `int64_t` is that `Monitor::wait()` takes an `int64_t`. Albert filed an issue to change that: [JDK-8255119](https://bugs.openjdk.java.net/browse/JDK-8255119), but until that is fixed I prefer using the same type here.

> src/hotspot/share/gc/g1/g1ServiceThread.hpp line 114:
>> 112:   G1ServiceThread();
>> 113:   double vtime_accum() { return _vtime_accum; }
>> 114:   void register_task(G1ServiceTask* task, jlong delay = 0);
> Please add a comment what the delay means, i.e. something like: automatically schedules the task with the given delay.
> From what is written here I am actually a bit confused about the difference between `register_task()` and `schedule_task()`. One seems to be to use by *other* threads, and the other one should only be called by a `ServiceTask` (in context of the `ServiceThread`).
> Do we actually need to make a difference between these two and/or do both need to be public? At first glance I would not be sure who is allowed to call which and what the difference actually is.
> It also seems that if either is called by the wrong thread bad things happen. Maybe it is possible to add some asserts to warn about most unintentional misuse?

I agree these are very similar and as you say it's not good that both are public, I changed this by making `G1ServiceTask` a friend of `G1ServiceThread`, so that `schedule_task()` can be private. Also added short comments to help when only reading the interface.

> src/hotspot/share/gc/g1/g1ServiceThread.hpp line 70:
>> 68: };
>> 69: 
>> 70: class G1ServiceTaskQueue {
> Maybe add:
> // Time ordered list of tasks to execute.

I find this covered by the comment just below.

> src/hotspot/share/gc/g1/g1ServiceThread.hpp line 46:
>> 44:   G1ServiceTask(const char* name);
>> 45:   const char* name();
>> 46:   void set_service_thread(G1ServiceThread* thread);
> maybe just make the `ServiceThread` a friend of `ServiceTask(Queue)` to avoid the setters (`set_service_thread` and `set_time` and probably others)?
> In the end you can't use one without the others anyway, i.e. they are already very tightly coupled.
> These management methods seem to only clutter the public interface (i.e. you can still use the methods internally)

Made both `G1ServiceThread` and `G1ServiceTaskQueue` friends with `G1ServiceTask`, so now all setters are either private or protected. The ones that are protected are used by either tests and/or the sentinel task. These could also be made private and list all tasks needing them as friends, but I went with this solution. What do you think?

> src/hotspot/share/gc/g1/g1ServiceThread.hpp line 73:
>> 71:   // The sentinel task is the entry point of this priority queue holding the
>> 72:   // service tasks. The queue is ordered by the time the tasks are scheduled
>> 73:   // to run and the sentinel task has the time set to DBL_MAX. This guarantees
> s/DBL_MAX/max_jlong. Maybe just something like: the sentinel task is put at the end of the queue to simplify list management.



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

More information about the hotspot-gc-dev mailing list