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:
parent
d76cfab002
commit
c4d647ea1b
2 changed files with 78 additions and 49 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue