Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4356620

JVMPI_EVENT_MONITOR_WAITED sent before wait is actually complete

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P2 P2
    • 1.3.1
    • 2.0
    • vm-legacy
    • beta
    • x86
    • windows_nt
    • Not verified



        Name: cl74495 Date: 07/26/2000


        With "Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)" our
        JVMPI client is seeing MONITOR_WAITED events before the thread that
        owns the monitor (and did the notify) has released the monitor. This
        is a change from 1.2.2.

        The effect is that for our thread analysis tool, it incorrectly
        reports data races and fails to report thread stalls. It also impacts
        a performance monitor feature under consideration, because the timeout
        send with the MONITOR_WAITED event will not accurately reflect the
        amount of time the thread really spent waiting. The false-positive
        data races are a serious enough problem to prevent a release of the
        product that supports HotSpot.

        Compile Waits.java (below), and make jvmpi_tool.dll from the C++ source
        below. Run as:

        java -Xrunjvmpi_tool Wait

        The program will hang (this is as it should be) and the output will
        look something like:

        00766274: Finalizer
        00766F34: Reference Handler
        00762A54: main
        00769594: Signal Dispatcher
        00762A54: MONITOR_WAIT: object 02AA5DB8, timeout 0
        0076CC24: A
        0076CC24: MONITOR_WAIT: object 02AA5DB8, timeout 0
        0076DF74: B
        00762A54: MONITOR_WAITED: object 02AA5DB8, timeout 0
        0076CC24: MONITOR_WAITED: object 02AA5DB8, timeout 0

        Note that threads "A" and "main" both received MONITOR_WAITED
        events, despite the fact that thread "B" is in an infinite loop
        and still holds the monitor. Compare this with output from 1.2.2:

        008104E0: Signal dispatcher
        00810D40: Reference Handler
        00811E80: Finalizer
        00825B80: SymcJIT-LazyCompilation-PA
        007C1170: main
        007C1170: MONITOR_WAIT: object 01A75D60, timeout 0
        00846890: A
        00846890: MONITOR_WAIT: object 01A75D60, timeout 0
        00847100: B
        00825360: SymcJIT-LazyCompilation-0

        Notice the MONITOR_WAITED event is never sent. And IBM's 1.3, which
        uses a locking scheme similar to HotSpot gets this right as well, so
        don't tell me you can't do it. :-)

        -------------- Waits.java --------------
        import java.lang.*;

        public class Waits
        {
        public static NaiveBarrier barrier;

        public static void main(String[] args)
        {
        new Waits().go();
        }

        public void go()
        {
        barrier = new NaiveBarrier(3);

        new Thread(new SubThread(), "A").start();
        new Thread(new SubThread(), "B").start();

        barrier.reach();
        }

        protected static class SubThread implements Runnable
        {
        public void run() {
        Waits.barrier.reach();
        }
        }

        protected static class NaiveBarrier {

        protected int barrierSize;
        protected int waitingThreads = 0;

        public NaiveBarrier (int size) {
        barrierSize = size;
        }

        public synchronized void reach () {
        try {
        if (++waitingThreads == barrierSize) {
        notifyAll();
        // Spin forever
        for (;;) {}
        } else {
        wait();
        }
        } catch (InterruptedException ie) {
        } finally {
        --waitingThreads;
        }
        }
        }
        }
        --------------------------------------------
        #include <stdio.h>
        #include <jvmpi.h>

        #define JVMPI(m) (jvmpi->m)

        static JVMPI_Interface *jvmpi;
        static void notify(JVMPI_Event *);

        extern "C" JNIEXPORT jint JNICALL
        JVM_OnLoad(JavaVM *jvm, char *options, void *reserved)
        {
        int res = jvm->GetEnv((void **)&jvmpi, JVMPI_VERSION_1);

        if (res < 0) {
        return JNI_ERR;
        }

        jvmpi->NotifyEvent = notify;

        JVMPI(EnableEvent)(JVMPI_EVENT_JVM_INIT_DONE, NULL);
        JVMPI(EnableEvent)(JVMPI_EVENT_THREAD_START, NULL);
        JVMPI(EnableEvent)(JVMPI_EVENT_MONITOR_WAIT, NULL);
        JVMPI(EnableEvent)(JVMPI_EVENT_MONITOR_WAITED, NULL);

        if (options && *options) {
        int val = atoi(options);
        if (val) {
        delay = val;
        }
        }

        return JNI_OK;
        }

        static bool inited;

        void
        notify(JVMPI_Event * event)
        {
        switch (event->event_type) {
        case JVMPI_EVENT_JVM_INIT_DONE:
        inited = true;
        break;
        case JVMPI_EVENT_THREAD_START:
        printf("%p: %s\n",
        event->u.thread_start.thread_env_id,
        event->u.thread_start.thread_name);
        break;
        case JVMPI_EVENT_MONITOR_WAIT:
        if (inited) {
        printf("%p: MONITOR_WAIT: object %p, timeout %ld\n",
        event->env_id,
        event->u.monitor_wait.object,
        (long) event->u.monitor_wait.timeout);
        }
        break;
        case JVMPI_EVENT_MONITOR_WAITED:
        if (inited) {
        printf("%p: MONITOR_WAITED: object %p, timeout %ld\n",
        event->env_id,
        event->u.monitor_wait.object,
        (long) event->u.monitor_wait.timeout);
        }
        break;
        default:
        break;
        }
        }
        -------------- jvmpi_tool.cpp --------------
        (Review ID: 107439)
        ======================================================================

              dcubed Daniel Daugherty
              clucasius Carlos Lucasius (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: