RFR(S): 7037756 Deadlock in compiler thread similiar to 6789220

John Cuthbertson john.cuthbertson at oracle.com
Tue Apr 26 17:55:11 UTC 2011


Hi Tom, Rmki,

I think that the main loop might still get compiled (some of the time) 
even with this fix. Here's the code of the run method:

        public void run() {
            for (;;) {

                Reference r;
                synchronized (lock) {
                    if (pending != null) {
                        r = pending;
                        Reference rn = r.next;
                        pending = (rn == r) ? null : rn;
                        r.next = r;
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException x) { }
                        continue;
                    }
                }

                // Fast path for cleaners
                if (r instanceof Cleaner) {
                    ((Cleaner)r).clean();
                    continue;
                }

                ReferenceQueue q = r.queue;
                if (q != ReferenceQueue.NULL) q.enqueue(r);
            }
        }

With Xcomp, the reference handler thread is not holding the lock when 
run() is called and so the compilation request would be successful. 
Normally though the compilation of run() would be an OSR compilation - 
it looks like there are 3 backward branches and only one of which is 
inside the the locked region. If we have a lot of references to enqueue 
then I would expect that the backward branch after the enqueue() call 
would trigger an OSR compile (I don't think the branch inside the locked 
region would be executed any more frequently).

The actual method I saw being compiled while holding the pending list 
lock was: 
java/lang/ref/Reference.access$202:(Ljava/lang/ref/Reference;)Ljava/lang/ref/Reference;

Other methods invoked from the locked region are:

java/lang/ref/Reference.access$200:()Ljava/lang/ref/Reference;
java/lang/ref/Reference.access$100:()Ljava/lang/ref/Reference$Lock;
java/lang/Object.wait:()V

Of these 
java/lang/ref/Reference.access$100:()Ljava/lang/ref/Reference$Lock; is 
also invoked outside of the locked region (it's actually at bci:0 - 
which is the target bci of the backward branches), and 
java/lang/Object.wait:()V is a native method.


On 04/25/11 19:58, Tom Rodriguez wrote:
>
> We could have a small side queue that we could enqueue these on and when a later safe request comes in we can request a non blocking compile of them.  It's kind of gross but it would work I think.  It could even just be a queue of length one instead of a full data structure.
>
> tom
>
>   
I think having a special queue for these is a lot uglier than adapting 
the original fix (i.e. the one with the try_lock) to use ownership of 
the pending list lock rather than the thread id.

JohnC

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/hotspot-gc-dev/attachments/20110426/54b165a3/attachment.htm>


More information about the hotspot-gc-dev mailing list