/******************************************************************************* * Copyright (c) 2010 Freescale Semiconductor. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Serge Beauchamp (Freescale Semiconductor) - initial API and implementation *******************************************************************************/ package com.freescale.deadlockpreventer; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; public class LockInfo { private Object lock; private Integer lockKey; // This is not normally set, except from statistic gathering String lockID; public void setLock(Object lock) { this.lock = lock; lockKey = ObjectCache.getKey(lock); lockID = null; } public Object getLock() { return lock; } public Integer getLockKey() { return lockKey; } String threadId = null; int count = 0; StackTraceElement[] stackTrace; HashMap<String, StackTraceElement[]> contextsPerThread = new HashMap<String, StackTraceElement[]>(); ArrayList<LockInfo> guards = null; ArrayList<LockInfo> phantomGuards = null; LockInfo acquiringContext = null; public void print(String header) { StringBuffer buffer = new StringBuffer(); Logger.printStrackTrace(buffer, header, stackTrace, Logger.FIRST_STACK_TRACE_ELEMENT); System.out.print(buffer.toString()); } public void print(StringBuffer buffer, String header) { Logger.printStrackTrace(buffer, header, stackTrace, Logger.FIRST_STACK_TRACE_ELEMENT); } public String toString() { return "LockInfo: " + Util.getUniqueIdentifier(lock); } public LockInfo copy() { LockInfo info = new LockInfo(); info.lock = lock; info.threadId = threadId; info.lockKey = lockKey; info.stackTrace = stackTrace; return info; } public void registerContext(String threadID, StackTraceElement[] context, ArrayList<LockInfo> guardList) { if (!contextsPerThread.containsKey(threadID)) contextsPerThread.put(threadID, context); mergeGuardList(guardList); } public boolean equals(Object o) { if (o instanceof LockInfo) return ((LockInfo)o).lock == lock; return false; } @SuppressWarnings("unchecked") private void mergeGuardList(ArrayList<LockInfo> guardList) { if (guards == null) guards = (ArrayList<LockInfo>) guardList.clone(); else { ArrayList<LockInfo> tmp = null; for (LockInfo guard : guards) { if (!guardList.contains(guard)) { if (tmp == null) tmp = new ArrayList<LockInfo>(); tmp.add(guard); } } if (tmp != null) { for (LockInfo toMove : tmp) { guards.remove(toMove); initPhantoms(); phantomGuards.add(toMove); } } for (LockInfo guard : guardList) { if (!guards.contains(guard)) { initPhantoms(); if (!phantomGuards.contains(guard)) phantomGuards.add(guard); } } } } private void initPhantoms() { if (phantomGuards == null) phantomGuards = new ArrayList<LockInfo>(); } public ArrayList<Entry<String, StackTraceElement[]>> getConflictingThreads( List<LockInfo> guards, String threadID) { ArrayList<Entry<String, StackTraceElement[]>> set = new ArrayList<Entry<String, StackTraceElement[]>>(); Iterator<Entry<String, StackTraceElement[]>> iterator = contextsPerThread.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, StackTraceElement[]> entry = iterator.next(); if (!entry.getKey().equals(threadID)) set.add(entry); } return set; } public StackTraceElement[] getContext(String threadID) { return contextsPerThread.get(threadID); } public boolean containsCommonGuard(List<LockInfo> subList) { for (LockInfo lockInfo : subList) { if (guards.contains(lockInfo)) return true; } return false; } public ArrayList<Entry<String, StackTraceElement[]>> findOtherContextThanThread(String threadID) { ArrayList<Entry<String, StackTraceElement[]>> set = new ArrayList<Entry<String, StackTraceElement[]>>(); Iterator<Entry<String, StackTraceElement[]>> iterator = contextsPerThread.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, StackTraceElement[]> entry = iterator.next(); if (!entry.getKey().equals(threadID)) set.add(entry); } return set; } public void setAcquiringContext(LockInfo info) { acquiringContext = info; } public LockInfo getAquiringContext() { return acquiringContext; } }