--- /dev/null 2016-10-25 08:46:44.038854975 +0200
+++ new/src/share/classes/sun/evtracing/processing/statistics/MonitorContender.java 2016-10-25 10:40:48.749803722 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ *
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see .
+ *
+ */
+package sun.evtracing.processing.statistics;
+
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorEnterWait;
+import sun.evtracing.parser.MonitorEnteredFlags;
+import sun.evtracing.parser.MonitorEvent;
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.Sanity;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+
+public class MonitorContender {
+
+ private final JavaObjectStack objectStack;
+ private final ContentionProcessor processor;
+ private final MonitorContendedEnterEvent enter;
+
+ private MonitorEvent lastEvent;
+
+ public static MonitorContender forEnter(JavaObjectStack objectStack, MonitorContendedEnterEvent event, ContentionProcessor processor) {
+ return new MonitorContender(objectStack, event, processor);
+ }
+
+ private MonitorContender(JavaObjectStack objectStack, MonitorContendedEnterEvent event, ContentionProcessor processor) {
+ this.objectStack = objectStack;
+ this.enter = event;
+ this.processor = processor;
+ this.lastEvent = event;
+ }
+
+ private Group group() {
+ if (enter.afterWait() != MonitorEnterWait.NoWait) {
+ return Group.MonitorWaitReentry;
+ }
+ return Group.Monitors;
+ }
+
+ private boolean wasEntered() {
+ return (lastEvent.type() == TraceEventType.MonitorContendedEntered);
+ }
+
+ void contenderExitedMonitor(MonitorContendedExitedEvent exit) {
+ assert !wasEntered();
+ long startTime = lastEvent.timestamp();
+ long duration = exit.timestamp() - startTime;
+ processor.submit(new Contention(group(), enter.thread().metadata(), exit.thread().metadata(), enter.stack().metadata(), exit.stack().metadata(), objectStack, startTime, duration));
+ lastEvent = exit;
+ }
+
+ void monitorContendedEntered(MonitorContendedEnteredEvent entered) {
+ assert !wasEntered();
+ if (entered.flags().contains(MonitorEnteredFlags.Queued)) {
+ if (entered.flags().contains(MonitorEnteredFlags.Parked)) {
+ Sanity.warnIf(lastEvent == enter, "entered monitor after parking without prior contender exit (rare race)");
+ } else {
+ Sanity.warnIf(lastEvent == enter, "entered monitor after queueing without prior contender exit (race)");
+ }
+ } else {
+ // the thread managed to obtain the lock only by spinning, not entering
+ // itself on any queue. therefore, the contender could not have noticed it
+ // and has not written an exit event unless another thread was waiting.
+ }
+ // attribute period between last exit and entered to unknown
+ long startTime = lastEvent.timestamp();
+ long duration = entered.timestamp() - startTime;
+ processor.submit(new Contention(group(), enter.thread().metadata(), JavaThread.UNKNOWN, enter.stack().metadata(), JavaStack.UNKNOWN, objectStack, startTime, duration));
+ lastEvent = entered;
+ }
+
+ void monitorContendedExited(long time) {
+ // nothing to do so far
+ }
+
+ @Override
+ public String toString() {
+ return enter.thread().metadata().toString() + " blocking on " + objectStack.toString();
+ }
+
+}