Hi all,

thank you very much for your explanations. I did not know about lock deflation - now wait/notify makes more sense.
I wrote a small program which reveals a problem in the wait/notify/locking implementation. I think that the following code
must not throw an exception:


public class Bug {
    public static final Object lock = new Object();

    public static void main(String[] args) {
        Thread t1 = new Thread(new C0(lock));
        Thread t2 = new Thread(new C1(lock));

        t1.start();
        t2.start();

        while (true) {}
    }
}

class C0 implements Runnable {
    final Object lock;

    public C0(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (lock) {
                try {
                    lock.wait();
                    //System.out.println("woken up");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

class C1 implements Runnable {

    final Object lock;

    public C1(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (lock) {
               
                lock.notify(); //exception here
            }
        }
    }
}


However, executing the program on my system results in the following IllegalMonitorStateException

Exception in thread "Thread-2" java.lang.IllegalMonitorStateException: notifyingjava.lang.Object@2583f9fc
   at org.jikesrvm.scheduler.RVMThread.raiseIllegalMonitorStateException(RVMThread.java:3034)
   at org.jikesrvm.scheduler.RVMThread.notify(RVMThread.java:3052)
   at java.lang.Object.notify(Object.java:52)
   at C1.run(Bug.java:51)
   at java.lang.Thread.run(Thread.java:745)


I executed the code above on an unmodified version of Jikes 3.1.1 (prototype-opt) with the parameter:
-X:aos:enable_recompilation=false

on a 32-bit Ubuntu system.

( 2.6.32-30-generic #59-Ubuntu SMP Tue Mar 1 21:30:21 UTC 2011 i686 GNU/Linux, Intel(R) Core(TM) i7 CPU)

Can anyone reproduce the error?


Cheers,
Albert


On Thu, Apr 14, 2011 at 2:07 AM, Ahmed Hussein <hussein@cs.purdue.edu> wrote:


On Wed, Apr 13, 2011 at 7:40 PM, Daniel Frampton <zyridium@zyridium.net> wrote:
Hi Albert,
 
I don't have the time to dig in to the precise details, but hopefully I can give you some useful pointers.
 
On Wed, Apr 13, 2011 at 5:57 PM, albert noll <noll.albert@gmail.com> wrote:
Hi,

I have a question concerning the wait/notify(All) implementation in the most recent version of JikesRVM (3.1.1).

1) How can it be that the lock is zero when notifyAll in RVMThread.java is invoked? According to the JLS, the calling thread must own the lock.
   
here is the code snippet from RVMThread,java:
...
       Lock l = ObjectModel.getHeavyLock(o, false);
       if (l == null)
          return;
...
 
If a lock is uncontended and held by a single thread, then no 'heavy' lock will exist and it is still legal to call notifyAll (which will be a no-op since nobody could be waiting).
 
 
2) In the function waitImpl in RVMThread.java:
  a) What is the purpose if the field?
         ...
         protected Object waitObject;
         ...
     It is written twice but never read.
 
I assume that this code was used for debugging and is no longer necessary.
 
 
  b) How can it be possible that after a thread is woken up (from the wait method) that the object on which the thread waited has
      no associated lock? I am just asking because the second parameter (see below) is set to true.
            ... // from wiatImpl in RVMThread.java
            if (waitCount != 1) { // reset recursion count
                Lock l2 = ObjectModel.getHeavyLock(o, true);
                l2.setRecursionCount(waitCount);
            }
            ...
 
If the lock exists as you expect, then of course the true will be no effect. However, we do have a system (not sure if it is the default) with eager deflation of locks. Once the lock is no longer held and the thread is not on the wait list, it would be possible (although perhaps unlikely) for the lock to be deflated by another thread before that point in the code.
-The waiting thread maybe deqeued from the waiting queue without a notify. In this case another thread checks the entering and waiting queues. if the latter thread finds them empty it may deflate the lock.
 
 
   c) Why is a waiting thread woken up if a second thread waits on the same object?
            // release the lock
            l.mutex.lock();
            RVMThread toAwaken = l.entering.dequeue();
            waitObject = l.getLockedObject();
            waitCount = l.getRecursionCount();
            l.setOwnerId(0);
            l.waiting.enqueue(this);
            l.mutex.unlock();

 
I am not sure I follow the question. A thread "waiting-to-enter" is dequed, and the current thread is placed on the waiting list? No "waiting" thread is woken here so far as I can see.
 
 
   d) Isn't there a data race between the following line in waitImpl

            1) while (l.waiting.isQueued(this) && !hasInterrupt && asyncThrowable == null && (!hasTimeout || sysCall.sysNanoTime() <       whenWakeupNanos)) {               

     and the lines in notify(All)

        l.mutex.lock();
       2) RVMThread toAwaken = l.waiting.dequeue();
        l.mutex.unlock();

  Can't the read in (1) happen concurrently with the write in (2)?
 
The read in 1 and the write in 2 can happen in any order. However, the read in (1) happens while the thread holds its mutex, as does the broadcast that occurs after (2). So I can't see how (2) can run and leave the waiting thread inside its loop, which is the case you are concerned about?
 
I want to make sure that I understand the wait/notify implementation in Jikes, since I am currently trying to find a bug: A thread waits on an object A, however, although calling notifyAll on A the waiting thread does no-t wake up.

 
Do you have code to reproduce this easily? We could include it as a unit test and then when one of us has time we may be able to help solve the issue.
 
Cheers,
Daniel.
 
Many thanks for your help.

Cheers,
Albert

------------------------------------------------------------------------------
Forrester Wave Report - Recovery time is now measured in hours and minutes
not days. Key insights are discussed in the 2010 Forrester Wave Report as
part of an in-depth evaluation of disaster recovery service providers.
Forrester found the best-in-class provider in terms of services and vision.
Read this report now!  http://p.sf.net/sfu/ibm-webcastpromo
_______________________________________________
Jikesrvm-researchers mailing list
Jikesrvm-researchers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jikesrvm-researchers



------------------------------------------------------------------------------
Benefiting from Server Virtualization: Beyond Initial Workload
Consolidation -- Increasing the use of server virtualization is a top
priority.Virtualization can reduce costs, simplify management, and improve
application availability and disaster protection. Learn more about boosting
the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev

_______________________________________________
Jikesrvm-researchers mailing list
Jikesrvm-researchers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jikesrvm-researchers



------------------------------------------------------------------------------
Benefiting from Server Virtualization: Beyond Initial Workload
Consolidation -- Increasing the use of server virtualization is a top
priority.Virtualization can reduce costs, simplify management, and improve
application availability and disaster protection. Learn more about boosting
the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev
_______________________________________________
Jikesrvm-researchers mailing list
Jikesrvm-researchers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jikesrvm-researchers