On Fri, 1 Mar 2024 11:50:05 GMT, Serguei Spitsyn <sspit...@openjdk.org> wrote:
>> The implementation of the JVM TI `GetObjectMonitorUsage` does not match the >> spec. >> The function returns the following structure: >> >> >> typedef struct { >> jthread owner; >> jint entry_count; >> jint waiter_count; >> jthread* waiters; >> jint notify_waiter_count; >> jthread* notify_waiters; >> } jvmtiMonitorUsage; >> >> >> The following four fields are defined this way: >> >> waiter_count [jint] The number of threads waiting to own this monitor >> waiters [jthread*] The waiter_count waiting threads >> notify_waiter_count [jint] The number of threads waiting to be notified by >> this monitor >> notify_waiters [jthread*] The notify_waiter_count threads waiting to be >> notified >> >> The `waiters` has to include all threads waiting to enter the monitor or to >> re-enter it in `Object.wait()`. >> The implementation also includes the threads waiting to be notified in >> `Object.wait()` which is wrong. >> The `notify_waiters` has to include all threads waiting to be notified in >> `Object.wait()`. >> The implementation also includes the threads waiting to re-enter the monitor >> in `Object.wait()` which is wrong. >> This update makes it right. >> >> The implementation of the JDWP command `ObjectReference.MonitorInfo (5)` is >> based on the JVM TI `GetObjectMonitorInfo()`. This update has a tweak to >> keep the existing behavior of this command. >> >> The follwoing JVMTI vmTestbase tests are fixed to adopt to the >> `GetObjectMonitorUsage()` correct behavior: >> >> jvmti/GetObjectMonitorUsage/objmonusage001 >> jvmti/GetObjectMonitorUsage/objmonusage003 >> >> >> The following JVMTI JCK tests have to be fixed to adopt to correct behavior: >> >> vm/jvmti/GetObjectMonitorUsage/gomu001/gomu00101/gomu00101.html >> vm/jvmti/GetObjectMonitorUsage/gomu001/gomu00101/gomu00101a.html >> vm/jvmti/GetObjectMonitorUsage/gomu001/gomu00102/gomu00102.html >> vm/jvmti/GetObjectMonitorUsage/gomu001/gomu00102/gomu00102a.html >> >> >> >> A JCK bug will be filed and the tests have to be added into the JCK problem >> list located in the closed repository. >> >> Also, please see and review the related CSR: >> [8324677](https://bugs.openjdk.org/browse/JDK-8324677): incorrect >> implementation of JVM TI GetObjectMonitorUsage >> >> The Release-Note is: >> [8325314](https://bugs.openjdk.org/browse/JDK-8325314): Release Note: >> incorrect implementation of JVM TI GetObjectMonitorUsage >> >> Testing: >> - tested with mach5 tiers 1-6 > > Serguei Spitsyn has updated the pull request incrementally with one > additional commit since the last revision: > > rename after merge: jvmti_common.h to jvmti_common.hpp Thanks Serguei, this is generally looking good, but I have one main query with the logic, a number of suggestions regarding comments, and a few issues in the new test code. src/hotspot/share/prims/jvmtiEnvBase.cpp line 1489: > 1487: assert(mon != nullptr, "must have monitor"); > 1488: // this object has a heavyweight monitor > 1489: nWant = mon->contentions(); // # of threads contending for monitor Please clarity comment as // # of threads contending for monitor entry, but not -rentry src/hotspot/share/prims/jvmtiEnvBase.cpp line 1490: > 1488: // this object has a heavyweight monitor > 1489: nWant = mon->contentions(); // # of threads contending for monitor > 1490: nWait = mon->waiters(); // # of threads in Object.wait() Please clarify the comment as // # of threads waiting for notification, or to re-enter monitor, in Object.wait() src/hotspot/share/prims/jvmtiEnvBase.cpp line 1491: > 1489: nWant = mon->contentions(); // # of threads contending for monitor > 1490: nWait = mon->waiters(); // # of threads in Object.wait() > 1491: wantList = Threads::get_pending_threads(tlh.list(), nWant + nWait, > (address)mon); Please add a comment // Get the actual set of threads trying to enter, or re-enter, the monitor. src/hotspot/share/prims/jvmtiEnvBase.cpp line 1505: > 1503: // the monitor threads after being notified. Here we are > correcting the actual > 1504: // number of the waiting threads by excluding those re-entering > the monitor. > 1505: nWait = i; Sorry I can't follow the logic here. Why is the whole block not simply: if (mon != nullptry) { // The nWait count may include threads trying to re-enter the monitor, so // walk the actual set of waiters to count those actually waiting. int count = 0; for (ObjectMonitor * waiter = mon->first_waiter(); waiter != nullptr; waiter = mon->next_waiter(waiter)) { count++; } } ret.notify_waiter_count = count; src/hotspot/share/prims/jvmtiEnvBase.cpp line 1552: > 1550: // If the thread was found on the ObjectWaiter list, then > 1551: // it has not been notified. This thread can't change the > 1552: // state of the monitor so it doesn't need to be suspended. Not sure why suspension is being mentioned here. test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java line 31: > 29: * DESCRIPTION > 30: * The test checks if the JVMTI function GetObjectMonitorUsage returns > 31: * the expected values for the owner, entry_count, water_count s/water_count/waiter_count/ test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java line 40: > 38: * - owned object with N waitings to be notified > 39: * - owned object with N waitings to enter, from 0 to N waitings to > re-enter, > 40: * from N to 0 waitings to be notified "waitings" is not grammatically valid. Suggestion: s/waitings/threads waiting/ test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java line 42: > 40: * from N to 0 waitings to be notified > 41: * - all the above scenarios are executed with platform and virtual > threads > 42: * @requires vm.continuations Do we really require this? test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java line 132: > 130: // count of threads waiting to re-enter: 0 > 131: // count of threads waiting to be notified: > NUMBER_OF_WAITING_THREADS > 132: check(lockCheck, null, 0, // no owner thread AFAICS you are racing here, as the waiting threads can set `ready` but not yet have called `wait()`. To know for sure they are in `wait()` you need to acquire the monitor before checking (and release it again so that you test the no-owner scenario as intended). But this should probably be done inside `startWaitingThreads`. test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java line 319: > 317: try { > 318: ready = true; > 319: lockCheck.wait(); Spurious wakeups will break this test. They shouldn't happen but ... test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/libObjectMonitorUsage.cpp line 65: > 63: > 64: > 65: jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { Nit: there's a double space after jint test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/libObjectMonitorUsage.cpp line 219: > 217: } > 218: > 219: } // exnern "C" typo: exnern -> extern ------------- PR Review: https://git.openjdk.org/jdk/pull/17680#pullrequestreview-1913304471 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510543479 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510540981 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510544636 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510548391 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510549323 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510550756 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510551339 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510551516 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510556424 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510553511 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510557225 PR Review Comment: https://git.openjdk.org/jdk/pull/17680#discussion_r1510557802