Deadlock on class locks

Patrick Tullmann tullmann at cs.utah.edu
Tue Dec 14 11:26:54 PST 1999


The attached test case demonstrates a deadlock in classMethod.c.  The
root of the problem is that lots of code within Kaffe is using the
"public" class lock for internal locking.  This is bad, bad, bad, bad,
bad. Using the public lock internally creates deadlocks wrt to static
synchronized methods.

This particular case comes when a thread takes the JIT lock, and while
compiling a method goes to look some strings up in the class's
constant pool.  Looking a string up takes the class lock.  However,
another thread is executing a static synchronized method (thus it
holds the class lock) and tries to invoke another method, thus
entering the jit'r and it can't get the JIT lock.

There are probably several other such race conditions, considering the 
number of places lockMutex(&clazz->head) is called.  The class object
lock should *only* be used by Java-level code for synchronized blocks.

I will change lockMutex(&clazz->head) into lockClassInternal(clazz)
(and maybe lockConstantPoolOf(clazz)) and submit a patch in a couple
days... Any thoughts/suggestions?

(Perhaps a deeper problem is the unknown interactions between various
locks in the system, especially the global JIT lock...)

-Pat

----- ----- ---- ---  ---  --   -    -      -         -               -
Pat Tullmann                                       tullmann at cs.utah.edu
		 Does the name `Pavlov' ring a bell?


/**
 * Test case for deadlocking in the Jitter.
 *
 * Sequence of events:
 *
 *   A call to blockOnJitter locks the class lock
 *
 *   A call to blockInJitter starts the jit and then calls
 *   classMethod.c:resolveString() attempting to resolve the string for
 *   `blockInJitter'.  However, the blockOnJitter thread already has
 *   the class lock so it blocks.
 *
 *   Next the blockOnJitter thread tries to call the loop() method which
 *   blocks on the jitter lock
 *
 *   And we have deadlock...
 */
public class DeadLock
{
	private static void loop()
	{
		for( int lpc = 0; lpc < 100; lpc++ )
		{
		}
	}
	
	private static synchronized void blockInJitter()
	{
		System.out.println("This is blockInJitter");
	}
	
	private static synchronized void blockOnJitter()
	{
		System.out.println("blockOnJitter thread has the class lock");
		for( int lpc = 0; lpc < 100; lpc++ )
		{
		}
		System.out.println("Yielding for blockInJitter thread");
		Thread.yield();
		System.out.println("Get set to deadlock when calling loop()");
		DeadLock.loop();
	}
	
	public static void main(String args[]) throws Exception
	{
		Thread th1, th2;

		th1 = new Thread() {
			public void run()
			{
				System.out.println("Start blockOnJitter");
				DeadLock.blockOnJitter();
				System.out.println("End blockOnJitter");
			}
		};
		th2 = new Thread() {
			public void run()
			{
				System.out.println("Start blockInJitter");
				DeadLock.blockInJitter();
				System.out.println("End blockInJitter");
			}
		};
		th1.start();
		th2.start();
		th1.join();
		th2.join();
	}
}




More information about the kaffe mailing list