1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Improved pdom lock tracing, bug 271909.

This commit is contained in:
Markus Schorn 2009-07-16 10:03:46 +00:00
parent d76cfab002
commit c4d647ea1b
2 changed files with 78 additions and 49 deletions

View file

@ -283,7 +283,6 @@ public class PDOM extends PlatformObject implements IPDOM {
private HashMap<Object, Object> fResultCache= new HashMap<Object, Object>(); private HashMap<Object, Object> fResultCache= new HashMap<Object, Object>();
private List<IListener> listeners; private List<IListener> listeners;
protected ChangeEvent fEvent= new ChangeEvent(); protected ChangeEvent fEvent= new ChangeEvent();
private Map<Thread, int[]> fLockDebugging;
public PDOM(File dbPath, IIndexLocationConverter locationConverter, Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException { public PDOM(File dbPath, IIndexLocationConverter locationConverter, Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException {
this(dbPath, locationConverter, ChunkCache.getSharedInstance(), linkageFactoryMappings); this(dbPath, locationConverter, ChunkCache.getSharedInstance(), linkageFactoryMappings);
@ -294,7 +293,7 @@ public class PDOM extends PlatformObject implements IPDOM {
loadDatabase(dbPath, cache); loadDatabase(dbPath, cache);
this.locationConverter = locationConverter; this.locationConverter = locationConverter;
if (sDEBUG_LOCKS) { if (sDEBUG_LOCKS) {
fLockDebugging= new HashMap<Thread, int[]>(); fLockDebugging= new HashMap<Thread, DebugLockInfo>();
System.out.println("Debugging PDOM Locks"); //$NON-NLS-1$ System.out.println("Debugging PDOM Locks"); //$NON-NLS-1$
} }
} }
@ -1277,65 +1276,97 @@ public class PDOM extends PlatformObject implements IPDOM {
return new PDOMFileSet(); return new PDOMFileSet();
} }
// For debugging lock issues // For debugging lock issues
private static int[] getLockCounter(Map<Thread, int[]> lockDebugging) { static class DebugLockInfo {
int fReadLocks;
int fWriteLocks;
List<StackTraceElement[]> fTraces= new ArrayList<StackTraceElement[]>();
public int addTrace() {
fTraces.add(Thread.currentThread().getStackTrace());
return fTraces.size();
}
@SuppressWarnings("nls")
public void write(String threadName) {
System.out.println("Thread: '" + threadName + "': " + fReadLocks + " readlocks, " + fWriteLocks + " writelocks");
for (StackTraceElement[] trace : fTraces) {
System.out.println(" Stacktrace:");
for (StackTraceElement ste : trace) {
System.out.println(" " + ste);
}
}
}
public void inc(DebugLockInfo val) {
fReadLocks+= val.fReadLocks;
fWriteLocks+= val.fWriteLocks;
fTraces.addAll(val.fTraces);
}
}
// For debugging lock issues
private Map<Thread, DebugLockInfo> fLockDebugging;
// For debugging lock issues
private static DebugLockInfo getLockInfo(Map<Thread, DebugLockInfo> lockDebugging) {
assert sDEBUG_LOCKS; assert sDEBUG_LOCKS;
Thread key = Thread.currentThread(); Thread key = Thread.currentThread();
int[] result= lockDebugging.get(key); DebugLockInfo result= lockDebugging.get(key);
if (result == null) { if (result == null) {
result= new int[]{0,0}; result= new DebugLockInfo();
lockDebugging.put(key, result); lockDebugging.put(key, result);
} }
return result; return result;
} }
// For debugging lock issues // For debugging lock issues
static void incReadLock(Map<Thread, int[]> lockDebugging) { static void incReadLock(Map<Thread, DebugLockInfo> lockDebugging) {
int[] lockCounter = getLockCounter(lockDebugging); DebugLockInfo info = getLockInfo(lockDebugging);
lockCounter[0]++; info.fReadLocks++;
if (info.addTrace() > 10) {
outputReadLocks(lockDebugging);
}
} }
// For debugging lock issues // For debugging lock issues
@SuppressWarnings("nls") @SuppressWarnings("nls")
static void decReadLock(Map<Thread, int[]> lockDebugging) throws AssertionError { static void decReadLock(Map<Thread, DebugLockInfo> lockDebugging) throws AssertionError {
int[] counter= getLockCounter(lockDebugging); DebugLockInfo info = getLockInfo(lockDebugging);
if (counter[0] <= 0) { if (info.fReadLocks <= 0) {
outputReadLocks(lockDebugging); outputReadLocks(lockDebugging);
throw new AssertionError("Superfluous releaseReadLock"); throw new AssertionError("Superfluous releaseReadLock");
} }
if (counter[1] != 0) { if (info.fWriteLocks != 0) {
outputReadLocks(lockDebugging); outputReadLocks(lockDebugging);
throw new AssertionError("Releasing readlock while holding write lock"); throw new AssertionError("Releasing readlock while holding write lock");
} }
if (--counter[0] == 0) { if (--info.fReadLocks == 0) {
lockDebugging.remove(Thread.currentThread()); lockDebugging.remove(Thread.currentThread());
} else {
info.addTrace();
} }
} }
// For debugging lock issues // For debugging lock issues
@SuppressWarnings("nls") @SuppressWarnings("nls")
private void incWriteLock(int giveupReadLocks) throws AssertionError { private void incWriteLock(int giveupReadLocks) throws AssertionError {
int[] counter= getLockCounter(fLockDebugging); DebugLockInfo info = getLockInfo(fLockDebugging);
if (counter[0] != giveupReadLocks) { if (info.fReadLocks != giveupReadLocks) {
outputReadLocks(fLockDebugging); outputReadLocks(fLockDebugging);
throw new AssertionError("write lock with " + giveupReadLocks + " readlocks, expected " + counter[0]); throw new AssertionError("write lock with " + giveupReadLocks + " readlocks, expected " + info.fReadLocks);
} }
if (counter[1] != 0) if (info.fWriteLocks != 0)
throw new AssertionError("Duplicate write lock"); throw new AssertionError("Duplicate write lock");
counter[1]++; info.fWriteLocks++;
} }
// For debugging lock issues // For debugging lock issues
private void decWriteLock(int establishReadLocks) throws AssertionError { private void decWriteLock(int establishReadLocks) throws AssertionError {
int[] counter= getLockCounter(fLockDebugging); DebugLockInfo info = getLockInfo(fLockDebugging);
if (counter[0] != establishReadLocks) if (info.fReadLocks != establishReadLocks)
throw new AssertionError("release write lock with " + establishReadLocks + " readlocks, expected " + counter[0]); //$NON-NLS-1$ //$NON-NLS-2$ throw new AssertionError("release write lock with " + establishReadLocks + " readlocks, expected " + info.fReadLocks); //$NON-NLS-1$ //$NON-NLS-2$
if (counter[1] != 1) if (info.fWriteLocks != 1)
throw new AssertionError("Wrong release write lock"); //$NON-NLS-1$ throw new AssertionError("Wrong release write lock"); //$NON-NLS-1$
counter[1]= 0; info.fWriteLocks= 0;
if (counter[0] == 0) { if (info.fReadLocks == 0) {
fLockDebugging.remove(Thread.currentThread()); fLockDebugging.remove(Thread.currentThread());
} }
} }
@ -1356,29 +1387,29 @@ public class PDOM extends PlatformObject implements IPDOM {
// For debugging lock issues // For debugging lock issues
@SuppressWarnings("nls") @SuppressWarnings("nls")
private static void outputReadLocks(Map<Thread, int[]> lockDebugging) { private static void outputReadLocks(Map<Thread, DebugLockInfo> lockDebugging) {
System.out.println("--------------------- Lock Debugging -------------------------");
for (Thread th: lockDebugging.keySet()) { for (Thread th: lockDebugging.keySet()) {
int[] counts = lockDebugging.get(th); DebugLockInfo info = lockDebugging.get(th);
System.out.println(th.getName() + ":" + counts[0] + "," + counts[1]); info.write(th.getName());
for (StackTraceElement ste : th.getStackTrace()) {
System.out.println(" " + ste);
}
} }
System.out.println("---------------------------------------------------------------");
} }
// For debugging lock issues // For debugging lock issues
public void adjustThreadForReadLock(Map<Thread, int[]> lockDebugging) { public void adjustThreadForReadLock(Map<Thread, DebugLockInfo> lockDebugging) {
for (Thread th : lockDebugging.keySet()) { for (Thread th : lockDebugging.keySet()) {
int[] val= lockDebugging.get(th); DebugLockInfo val= lockDebugging.get(th);
if (val[0] > 0) { if (val.fReadLocks > 0) {
int[] myval= fLockDebugging.get(th); DebugLockInfo myval= fLockDebugging.get(th);
if (myval == null) { if (myval == null) {
myval= new int[] {0,0}; myval= new DebugLockInfo();
fLockDebugging.put(th, myval); fLockDebugging.put(th, myval);
} }
myval[0]++; myval.inc(val);
decReadLock(fLockDebugging); for (int i = 0; i < val.fReadLocks; i++) {
break; decReadLock(fLockDebugging);
}
} }
} }
} }

View file

@ -12,7 +12,6 @@ package org.eclipse.cdt.internal.core.pdom;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -29,6 +28,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragmentFileSet;
import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude; import org.eclipse.cdt.internal.core.index.IIndexFragmentInclude;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName; import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
import org.eclipse.cdt.internal.core.pdom.PDOM.ChangeEvent; import org.eclipse.cdt.internal.core.pdom.PDOM.ChangeEvent;
import org.eclipse.cdt.internal.core.pdom.PDOM.DebugLockInfo;
import org.eclipse.cdt.internal.core.pdom.PDOM.IListener; import org.eclipse.cdt.internal.core.pdom.PDOM.IListener;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -43,11 +43,11 @@ public class PDOMProxy implements IPDOM {
private PDOM fDelegate; private PDOM fDelegate;
private int fReadLockCount; private int fReadLockCount;
private Set<IListener> fListeners= new HashSet<IListener>(); private Set<IListener> fListeners= new HashSet<IListener>();
private Map<Thread, int[]> fLockDebugging; private Map<Thread, DebugLockInfo> fLockDebugging;
public PDOMProxy() { public PDOMProxy() {
if (PDOM.sDEBUG_LOCKS) { if (PDOM.sDEBUG_LOCKS) {
fLockDebugging= new HashMap<Thread, int[]>(); fLockDebugging= new HashMap<Thread, DebugLockInfo>();
} }
} }
public synchronized void acquireReadLock() throws InterruptedException { public synchronized void acquireReadLock() throws InterruptedException {
@ -229,21 +229,19 @@ public class PDOMProxy implements IPDOM {
while (fReadLockCount > 0) { while (fReadLockCount > 0) {
pdom.acquireReadLock(); pdom.acquireReadLock();
fReadLockCount--; fReadLockCount--;
if (PDOM.sDEBUG_LOCKS) {
pdom.adjustThreadForReadLock(fLockDebugging);
}
} }
if (PDOM.sDEBUG_LOCKS) {
pdom.adjustThreadForReadLock(fLockDebugging);
}
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
for (Iterator<IListener> iterator = fListeners.iterator(); iterator.hasNext();) { for (IListener listener : fListeners) {
IListener listener = iterator.next();
pdom.addListener(listener); pdom.addListener(listener);
} }
ChangeEvent event= new ChangeEvent(); ChangeEvent event= new ChangeEvent();
event.setReloaded(); event.setReloaded();
for (Iterator<IListener> iterator = fListeners.iterator(); iterator.hasNext();) { for (IListener listener : fListeners) {
IListener listener = iterator.next();
listener.handleChange(fDelegate, event); listener.handleChange(fDelegate, event);
} }
} }