From c4d647ea1bedae35e70c6438116ed95acaeb766a Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 16 Jul 2009 10:03:46 +0000 Subject: [PATCH] Improved pdom lock tracing, bug 271909. --- .../eclipse/cdt/internal/core/pdom/PDOM.java | 109 +++++++++++------- .../cdt/internal/core/pdom/PDOMProxy.java | 18 ++- 2 files changed, 78 insertions(+), 49 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index b727db82a83..fd879e803c4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -283,7 +283,6 @@ public class PDOM extends PlatformObject implements IPDOM { private HashMap fResultCache= new HashMap(); private List listeners; protected ChangeEvent fEvent= new ChangeEvent(); - private Map fLockDebugging; public PDOM(File dbPath, IIndexLocationConverter locationConverter, Map 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(); + fLockDebugging= new HashMap(); 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 lockDebugging) { + static class DebugLockInfo { + int fReadLocks; + int fWriteLocks; + List fTraces= new ArrayList(); + 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 fLockDebugging; + + // For debugging lock issues + private static DebugLockInfo getLockInfo(Map 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 lockDebugging) { - int[] lockCounter = getLockCounter(lockDebugging); - lockCounter[0]++; + static void incReadLock(Map lockDebugging) { + DebugLockInfo info = getLockInfo(lockDebugging); + info.fReadLocks++; + if (info.addTrace() > 10) { + outputReadLocks(lockDebugging); + } } // For debugging lock issues @SuppressWarnings("nls") - static void decReadLock(Map lockDebugging) throws AssertionError { - int[] counter= getLockCounter(lockDebugging); - if (counter[0] <= 0) { + static void decReadLock(Map 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 lockDebugging) { + private static void outputReadLocks(Map 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 lockDebugging) { + public void adjustThreadForReadLock(Map 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); + } } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java index d6e5b17dd2b..0b7218befba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMProxy.java @@ -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 fListeners= new HashSet(); - private Map fLockDebugging; + private Map fLockDebugging; public PDOMProxy() { if (PDOM.sDEBUG_LOCKS) { - fLockDebugging= new HashMap(); + fLockDebugging= new HashMap(); } } 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 iterator = fListeners.iterator(); iterator.hasNext();) { - IListener listener = iterator.next(); + for (IListener listener : fListeners) { pdom.addListener(listener); } ChangeEvent event= new ChangeEvent(); event.setReloaded(); - for (Iterator iterator = fListeners.iterator(); iterator.hasNext();) { - IListener listener = iterator.next(); + for (IListener listener : fListeners) { listener.handleChange(fDelegate, event); } }