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

View file

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