diff --git a/.gitignore b/.gitignore
index 1c7316f58e5492487998c725c3f3de51f5c42ec8..dea77e5f7aa2edc180c8177e5d7e555a239c6467 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ workspace/
 states/
 .DS_Store
 screenshots/
+ajcore.*.txt
diff --git a/org.lamport.tla.toolbox.doc/META-INF/MANIFEST.MF b/org.lamport.tla.toolbox.doc/META-INF/MANIFEST.MF
index 8bfc83d2f6abbdd5bd55ad83d5126c6e81bbc537..89939ce998431311287a8062fc35a66a44add039 100644
--- a/org.lamport.tla.toolbox.doc/META-INF/MANIFEST.MF
+++ b/org.lamport.tla.toolbox.doc/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: TLA+ Toolbox Help
 Bundle-SymbolicName: org.lamport.tla.toolbox.doc; singleton:=true
-Bundle-Version: 1.5.0.qualifier
+Bundle-Version: 1.5.1.qualifier
 Bundle-RequiredExecutionEnvironment: J2SE-1.4
 Bundle-Vendor: Simon Zambrovski, Leslie Lamport
 Bundle-ActivationPolicy: lazy
diff --git a/org.lamport.tla.toolbox.doc/pom.xml b/org.lamport.tla.toolbox.doc/pom.xml
index d31cecdde6832ee897dc667a2d135e132681eb74..00918419ce09ee13dfb9f5327201262aeaf9347a 100644
--- a/org.lamport.tla.toolbox.doc/pom.xml
+++ b/org.lamport.tla.toolbox.doc/pom.xml
@@ -11,6 +11,6 @@
   </parent>
   <groupId>tlatoolbox</groupId>
   <artifactId>org.lamport.tla.toolbox.doc</artifactId>
-  <version>1.5.0-SNAPSHOT</version>
+  <version>1.5.1-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/org.lamport.tla.toolbox.product.product/org.lamport.tla.toolbox.product.product.product b/org.lamport.tla.toolbox.product.product/org.lamport.tla.toolbox.product.product.product
index bc3001bf8d46044e2887f03faba5d82ac6020f2c..eb9fc20ee5a84937c71dc3efa2d537b9d2fbba00 100644
--- a/org.lamport.tla.toolbox.product.product/org.lamport.tla.toolbox.product.product.product
+++ b/org.lamport.tla.toolbox.product.product/org.lamport.tla.toolbox.product.product.product
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?pde version="3.5"?>
 
-<product name="TLA+ Toolbox" uid="org.lamport.tla.toolbox.product.product" id="org.lamport.tla.toolbox.product.standalone.product" application="org.lamport.tla.toolbox.application" version="1.5.0" useFeatures="true" includeLaunchers="true">
+<product name="TLA+ Toolbox" uid="org.lamport.tla.toolbox.product.product" id="org.lamport.tla.toolbox.product.standalone.product" application="org.lamport.tla.toolbox.application" version="1.5.1" useFeatures="true" includeLaunchers="true">
 
    <aboutInfo>
       <image path="/org.lamport.tla.toolbox.product.standalone/images/splash_small.png"/>
       <text>
          TLA+ Toolbox provides a user interface for TLA+ Tools. 
 
-This is Version 1.5.0 of 11 May 2015 and includes:
+This is Version 1.5.1 of UNRELEASED and includes:
   - SANY Version 2.1 of 24 February 2014
-  - TLC Version 2.06 of 9 May 2015
+  - TLC Version 2.07 of UNRELEASED
   - PlusCal Version 1.8 of 2 April 2013
   - TLATeX Version 1.0 of 12 April 2013
 
@@ -69,7 +69,7 @@ Please send us reports of problems or suggestions; see https://groups.google.com
       <plugin id="org.eclipse.equinox.http.registry" autoStart="true" startLevel="3" />
       <plugin id="org.lamport.tla.toolbox.jclouds" autoStart="true" startLevel="4" />
       <plugin id="sts" autoStart="true" startLevel="4" />
-      <property name="eclipse.buildId" value="1.5.0" />
+      <property name="eclipse.buildId" value="1.5.1" />
    </configurations>
 
    <repositories>
diff --git a/org.lamport.tla.toolbox.product.product/pom.xml b/org.lamport.tla.toolbox.product.product/pom.xml
index c1a8e757555c069c84976a22794c476613e29baf..ee6c51827a2bda72ad3e7d4a6596920232dbac96 100644
--- a/org.lamport.tla.toolbox.product.product/pom.xml
+++ b/org.lamport.tla.toolbox.product.product/pom.xml
@@ -75,7 +75,7 @@
                    over features. The version segment has to be manually increment
                    upon a release.  
                    see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357503#c22 -->
-              <archiveFileName>TLAToolbox-1.5.0</archiveFileName>
+              <archiveFileName>TLAToolbox-1.5.1</archiveFileName>
               <rootFolder>toolbox</rootFolder>
             </product>
           </products>
diff --git a/org.lamport.tla.toolbox.product.standalone/plugin.xml b/org.lamport.tla.toolbox.product.standalone/plugin.xml
index 5a54abdfd343c8244f91d86eca811fab8083849c..2834b8f619306a6f525b7629c3bf9bb50a30fa14 100644
--- a/org.lamport.tla.toolbox.product.standalone/plugin.xml
+++ b/org.lamport.tla.toolbox.product.standalone/plugin.xml
@@ -29,7 +29,7 @@
          </property>
          <property
                name="aboutText"
-               value="TLA+ Toolbox provides a user interface for TLA+ Tools. &#x0A;&#x0A;This is Version 1.5.0 of 11 May 2015 and includes:&#x0A;  - SANY Version 2.1 of 24 February 2014&#x0A;  - TLC Version 2.06 of 9 May 2015&#x0A;  - PlusCal Version 1.8 of 2 April 2013&#x0A;  - TLATeX Version 1.0 of 12 April 2013&#x0A;&#x0A;Don&apos;t forget to click on help.  You can learn about features that you never knew about or have forgotten.&#x0A;&#x0A;Please send us reports of problems or suggestions; see https://groups.google.com/d/forum/tlaplus .">
+               value="TLA+ Toolbox provides a user interface for TLA+ Tools. &#x0A;&#x0A;This is Version 1.5.1 of UNRELEASED and includes:&#x0A;  - SANY Version 2.1 of 24 February 2014&#x0A;  - TLC Version 2.07 of UNRELEASED&#x0A;  - PlusCal Version 1.8 of 2 April 2013&#x0A;  - TLATeX Version 1.0 of 12 April 2013&#x0A;&#x0A;Don&apos;t forget to click on help.  You can learn about features that you never knew about or have forgotten.&#x0A;&#x0A;Please send us reports of problems or suggestions; see https://groups.google.com/d/forum/tlaplus .">
          </property>
          <property
                name="aboutImage"
diff --git a/org.lamport.tla.toolbox.uitest/pom.xml b/org.lamport.tla.toolbox.uitest/pom.xml
index aef27b1446ea0e16433ad875ab90f07b74a2128e..17fd3fd9b207705aa3571190e9308c501baa40d0 100644
--- a/org.lamport.tla.toolbox.uitest/pom.xml
+++ b/org.lamport.tla.toolbox.uitest/pom.xml
@@ -18,7 +18,7 @@
   		<dependency>
             <groupId>org.aspectj</groupId>
             <artifactId>aspectjrt</artifactId>
-            <version>1.8.2</version>
+            <version>1.8.5</version>
         </dependency>
         <!-- Down below we manually install the standalone feature. Maven/Tycho isn't
         	 smart enough to figure this out by itself. Thus, we have to tell Tycho
diff --git a/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/ToolboxWelcomeView.java b/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/ToolboxWelcomeView.java
index c79137f07e88ed6ad402b0ecd8b46730966cc2f0..277fbeca3ba0a5f4fb9ac97b30072ee0b4739a71 100644
--- a/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/ToolboxWelcomeView.java
+++ b/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/ToolboxWelcomeView.java
@@ -201,7 +201,7 @@ public class ToolboxWelcomeView extends ViewPart
 		
 		final Label lblVersion = new Label(outerContainer, SWT.WRAP);
 		lblVersion.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
-		lblVersion.setText("Version 1.5.0  of 11 May 2015");
+		lblVersion.setText("Version 1.5.1  of UNRELEASED");
 		lblVersion.setBackground(backgroundColor);
     }
 
diff --git a/tlatools/.classpath b/tlatools/.classpath
index fd9cc77553e8417275d5c6a865aa7a5ac1a1d297..5df2c0e31ace0682e9abd3d638adafa4534c24fa 100644
--- a/tlatools/.classpath
+++ b/tlatools/.classpath
@@ -3,10 +3,12 @@
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry excluding="tlc2/tool/distributed/TLCServerMonitorAspect.aj|tlc2/tool/distributed/RMIMethodMonitorAspect.aj|tlc2/tool/distributed/RMIMethodMonitorAspect.aj|tlc2/tool/distributed/TLCServerMonitorAspect.aj" kind="src" path="src-aj"/>
+	<classpathentry excluding="tlc2/tool/WorkerMonitorAspect.aj|tlc2/tool/distributed/TLCServerMonitorAspect.aj|tlc2/tool/distributed/RMIMethodMonitorAspect.aj|tlc2/tool/distributed/RMIMethodMonitorAspect.aj|tlc2/tool/distributed/TLCServerMonitorAspect.aj" kind="src" path="src-aj"/>
 	<classpathentry kind="src" path="test"/>
 	<classpathentry kind="src" path="test-long"/>
 	<classpathentry kind="src" path="test-concurrent"/>
+	<classpathentry kind="src" path="test-verify"/>
 	<classpathentry kind="lib" path="lib/javax.mail.jar"/>
+	<classpathentry kind="lib" path="lib/jpf.jar"/>
 	<classpathentry kind="output" path="class"/>
 </classpath>
diff --git a/tlatools/build.ajproperties b/tlatools/build.ajproperties
index 720d23e719c760ed2bf639c20b76a167a95344a3..f81d23bbe290c85cac34a298e066f4d4fd6dddfd 100644
--- a/tlatools/build.ajproperties
+++ b/tlatools/build.ajproperties
@@ -1,2 +1,3 @@
-src.includes = src-aj/tlc2/tool/distributed/RMIMethodMonitorAspect.aj,\
+src.includes = src-aj/tlc2/tool/WorkerMonitorAspect.aj,\
+			   src-aj/tlc2/tool/distributed/RMIMethodMonitorAspect.aj,\
 			   src-aj/tlc2/tool/distributed/TLCServerMonitorAspect.aj
diff --git a/tlatools/customBuild.xml b/tlatools/customBuild.xml
index 7b5e2f6716b7c80b5812c457f2517604927b2fb1..f062665e9d0c452b5a1d712264ce952e6f3f93f1 100644
--- a/tlatools/customBuild.xml
+++ b/tlatools/customBuild.xml
@@ -18,13 +18,13 @@
 	</tstamp>
 
 	<!-- JaCoCo code coverage -->
-    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
-        <classpath path="lib/jacocoant.jar"/>
-    </taskdef>
+	<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
+		<classpath path="lib/jacocoant.jar"/>
+	</taskdef>
 
 	<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
 		<classpath>
-			<pathelement location="lib/aspectjtools.jar" />
+			<pathelement location="lib/aspectjtools-1.8.5.jar" />
 		</classpath>
 	</taskdef>
 
@@ -63,9 +63,17 @@
 	</target>
 
 	<target name="compile" depends="clean" description="Compile">
+		<echo>
+			================================================================
+			= The following warnings about sun.misc.Unsafe can be ignored. = 
+			= OffHeapDiskFPSet has been written using Unsafe to best use   =
+			= a computer's memory. If Unsafe is removed from the JVM,      =
+			= OffHeapDiskFPSet won't work anymore.                         =
+			================================================================
+		</echo>
 		<!-- compile -->
 		<mkdir dir="${class.dir}" />
-		<javac srcdir="${src.dir}" destdir="${class.dir}" debug="true" verbose="false" source="1.5" target="1.5">
+		<javac includeantruntime="false" srcdir="${src.dir}" destdir="${class.dir}" debug="true" verbose="false" source="1.5" target="1.5">
 			<!-- compilerarg value="-Xlint:deprecation"/-->
 			<classpath refid="project.classpath" />
 			<classpath>
@@ -84,13 +92,20 @@
 		</copy>
 	</target>
 
-	<target name="compile-aj" depends="compile" if="withaj">
+	<target name="compile-aj" if="withaj">
+		<echo>
+			====================================================================
+			= The following warnings (Xlint:adviceDidNotMatch) can be ignored. =
+			= We are doing load time weaving that kicks in when TLC gets       = 
+			= started, not when it is compiled.                                =
+			====================================================================
+		</echo>
 		<!-- compile aspectj related class files -->
-		<iajc destdir="${class.dir}" sourceRoots="${src-aj.dir}" debug="true" source="1.5" target="1.5">
+		<iajc destdir="${class.dir}" sourceRoots="${src-aj.dir}" debug="true">
 			<classpath refid="project.classpath" />
 			<classpath>
-				<pathelement location="lib/aspectjrt.jar" />
-				<pathelement location="lib/aspectjtools.jar" />
+				<pathelement location="lib/aspectjrt-1.8.5.jar" />
+				<pathelement location="lib/aspectjtools-1.8.5.jar" />
 				<pathelement path="${class.dir}" />
 			</classpath>
 		</iajc>
@@ -107,8 +122,8 @@
 		<!-- These files are requried for load time weaving and during runtime -->
 		<copy todir="${class.dir}/lib">
 			<fileset dir="lib/">
-				<include name="aspectjrt.jar" />
-				<include name="aspectjweaver.jar" />
+				<include name="aspectjrt-1.8.5.jar" />
+				<include name="aspectjweaver-1.8.5.jar" />
 			</fileset>
 		</copy>
 	</target>
@@ -120,15 +135,15 @@
 		<!-- The javax.mail dependency as well as javax.activation is also depended upon -->
 		<!-- by the tla2tools OSGi bundle and is expected to be the same version. -->
 		<unzip src="lib/javax.mail.jar" dest="${class.dir}"/>
-		
+
 		<!-- Extract javax.mail to maven classes folder. This script is triggered by -->
 		<!-- maven. However, maven compiles the code again to target/classes from -->
 		<!-- where it creates the plugin -->
 		<unzip src="lib/javax.mail.jar" dest="target/classes"/>
-		
+
 		<!-- TODO: add javax.activation to lib/ and extract it here too. Otherwise we have a -->
 		<!-- runtime dependency on Java 6. -->
-		
+
 		<!-- create a JAR file for the users -->
 		<mkdir dir="${dist.dir}" />
 		<jar destfile="${dist.file}">
@@ -152,7 +167,7 @@
 	<target name="test" description="Executes accompining unit tests" unless="test.skip">
 		<!-- compile unit tests -->
 		<mkdir dir="${test.class.dir}" />
-		<javac srcdir="${test.dir}" destdir="${test.class.dir}" debug="true" verbose="false" source="1.5" target="1.5">
+		<javac includeantruntime="false" srcdir="${test.dir}" destdir="${test.class.dir}" debug="true" verbose="false">
 			<classpath refid="project.classpath" />
 			<classpath>
 				<pathelement location="lib/junit-4.8.2.jar" />
@@ -171,6 +186,10 @@
 		<mkdir dir="${test.reports}" />
 		<jacoco:coverage destfile="target/code-coverage.exec">
 			<junit printsummary="yes" haltonfailure="no" haltonerror="no"  forkmode="perTest" fork="yes">
+				<!-- Uncomment to open a debug port in each forked VM to remote attach your Eclipse at port 1044.
+	            <jvmarg value="-Xdebug" />
+		        <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044" />
+				-->
 				<classpath refid="project.classpath" />
 				<classpath>
 					<pathelement location="lib/junit-4.8.2.jar" />
@@ -181,7 +200,7 @@
 					<pathelement path="${test.class.dir}" />
 				</classpath>
 				<formatter type="xml" />
-	
+
 				<!-- Pass the base path of the tlatools project to unit tests in case they need it to locate TLA+ specs or configs -->
 				<sysproperty key="basedir" value="${basedir}/"/>
 				<batchtest fork="yes" todir="${test.reports}">
@@ -204,10 +223,10 @@
 		<delete dir="${ws.class.dir}" deleteonexit="true"/>
 	</target>
 
-	<target name="test-dist" description="Executes accompining unit tests on jar file" depends="dist" unless="test.skip">
+	<target name="test-dist" description="Executes accompining unit tests on jar file" unless="test.skip">
 		<!-- compile unit tests -->
 		<mkdir dir="${test.class.dir}" />
-		<javac srcdir="${test.dir}" destdir="${test.class.dir}" debug="true" verbose="false" source="1.5" target="1.5">
+		<javac includeantruntime="false" srcdir="${test.dir}" destdir="${test.class.dir}" debug="true" verbose="false">
 			<classpath refid="project.classpath" />
 			<classpath>
 				<pathelement location="lib/junit-4.8.2.jar" />
@@ -217,7 +236,7 @@
 		</javac>
 		<!-- copy class.dir to path with whitespace -->
 		<!-- this is required by some tests to make sense -->
-		<!-- even throw a non digit in -->
+		<!-- even throw a "+" and whitespace into the mix -->
 		<property name="ws.class.dir" value="TLA+ Tools" />
 		<copy todir="${ws.class.dir}">
 			<fileset dir="${class.dir}" />
@@ -257,10 +276,10 @@
 		<delete dir="${ws.class.dir}" deleteonexit="true"/>
 	</target>
 
-	<target name="test-dist-long" description="Executes accompining long-running unit tests on jar file" depends="dist" unless="test.skip">
+	<target name="test-dist-long" description="Executes accompining long-running unit tests on jar file" unless="test.skip">
 		<!-- compile unit tests -->
 		<mkdir dir="${test.class.dir}" />
-		<javac srcdir="${test.dir}-long" destdir="${test.class.dir}" debug="true" verbose="false" source="1.5" target="1.5">
+		<javac includeantruntime="false" srcdir="${test.dir}-long" destdir="${test.class.dir}" debug="true" verbose="false">
 			<classpath refid="project.classpath" />
 			<classpath>
 				<pathelement location="lib/junit-4.8.2.jar" />
@@ -269,14 +288,17 @@
 		</javac>
 		<!-- copy class.dir to path with whitespace -->
 		<!-- this is required by some tests to make sense -->
-		<!-- even throw a non digit in -->
+		<!-- even throw a "+" and whitespace into the mix -->
 		<property name="ws.class.dir" value="TLA+ Tools" />
 		<copy todir="${ws.class.dir}">
 			<fileset dir="${class.dir}" />
 		</copy>
 		<!-- run junit tests on tlatools.jar -->
 		<mkdir dir="${test.reports}/onJarLong" />
-		<junit printsummary="yes" haltonfailure="no" haltonerror="no" maxmemory="1024m">
+		<junit printsummary="yes" haltonfailure="no" haltonerror="no" maxmemory="4096m" forkmode="perTest" fork="yes">
+			<jvmarg value="-javaagent:lib/aspectjweaver-1.8.5.jar" />
+			<sysproperty key="org.aspectj.weaver.showWeaveInfo" value="false"/>
+			<sysproperty key="aj.weaving.verbose" value="false"/>
 			<classpath refid="project.classpath" />
 			<classpath>
 				<pathelement location="lib/junit-4.8.2.jar" />
@@ -288,6 +310,16 @@
 
 			<batchtest fork="yes" todir="${test.reports}/onJarLong">
 				<fileset dir="${test.dir}-long">
+					<exclude name="**/MultiThreadedSpecTest.java"/>
+
+					<!-- The following tests take way too long (hours). -->
+					<!-- Reactivate when you start working on the fingerprint sets! -->
+					<exclude name="**/DiskFPSetTest.java"/>
+					<exclude name="**/FPSetTest.java"/>
+					<exclude name="**/MSBDiskFPSetTest.java"/>
+					<exclude name="**/OffHeapDiskFPSetTest.java"/>
+					<exclude name="**/DiskStateQueueTest.java"/>
+
 					<include name="**/*Test*.java" />
 				</fileset>
 			</batchtest>
@@ -297,6 +329,40 @@
 		<delete dir="${ws.class.dir}" deleteonexit="true"/>
 	</target>
 
+	<!-- -->
+	<target name="test-verify" description="Verifies TLC parts with NASA's pathfinder model checker">
+		<!-- Compile our boilerplate code needed to verify TLC. E.g. the StateQueueVerify creates -->
+		<!-- examplary produces & consumers and a dummy implementation of StateQueue. -->
+		<javac includeantruntime="false" srcdir="${test.dir}-verify" destdir="${test.class.dir}" debug="true" verbose="false">
+			<classpath refid="project.classpath" />
+			<classpath>
+				<pathelement path="${class.dir}" />
+				<pathelement location="lib/jpf.jar" />
+			</classpath>
+		</javac>
+
+		<mkdir dir="${test.reports}/verify" />
+		<junit printsummary="yes" haltonfailure="no" haltonerror="no" maxmemory="4096m" forkmode="perTest" fork="yes" 
+			dir="${basedir}/test-verify" >
+			<classpath refid="project.classpath" />
+			<classpath>
+				<pathelement location="lib/junit-4.8.2.jar" />
+				<pathelement location="lib/jpf.jar" />
+				<pathelement location="lib/jpf-classes.jar" />
+				<pathelement path="${class.dir}" />
+				<pathelement path="${test.class.dir}" />
+			</classpath>
+
+			<formatter type="xml" />
+
+			<batchtest fork="yes" todir="${test.reports}/verify">
+				<fileset dir="${test.dir}-verify">
+					<include name="**/*Test*.java" />
+				</fileset>
+			</batchtest>
+		</junit>
+	</target>
+
 	<target name="dist-mixed-jar" description="Build a distribution" depends="default">
 		<!-- create a JAR file for the users -->
 		<jar destfile="${dist-mixed.file.jar}">
diff --git a/tlatools/lib/aspectjrt.jar b/tlatools/lib/aspectjrt-1.8.5.jar
similarity index 52%
rename from tlatools/lib/aspectjrt.jar
rename to tlatools/lib/aspectjrt-1.8.5.jar
index 94f9410effc8f2ee025969d0ae525b9713b9677c..b8241c820410996cc4a13dc942c27c6b0d9d6050 100644
Binary files a/tlatools/lib/aspectjrt.jar and b/tlatools/lib/aspectjrt-1.8.5.jar differ
diff --git a/tlatools/lib/aspectjtools.jar b/tlatools/lib/aspectjtools-1.8.5.jar
similarity index 50%
rename from tlatools/lib/aspectjtools.jar
rename to tlatools/lib/aspectjtools-1.8.5.jar
index 544553980a92f17a4bb9a56ddc9cfe1c6fccec0c..31f045d54150a074202fafac517f9be9243d0519 100644
Binary files a/tlatools/lib/aspectjtools.jar and b/tlatools/lib/aspectjtools-1.8.5.jar differ
diff --git a/tlatools/lib/aspectjweaver-1.8.5.jar b/tlatools/lib/aspectjweaver-1.8.5.jar
new file mode 100644
index 0000000000000000000000000000000000000000..952a8e4c7cae616b1d20da5dde99a820911df527
Binary files /dev/null and b/tlatools/lib/aspectjweaver-1.8.5.jar differ
diff --git a/tlatools/lib/aspectjweaver.jar b/tlatools/lib/aspectjweaver.jar
deleted file mode 100644
index bfd54339ca8525f9a7acbadd1e48d2ff6353d81e..0000000000000000000000000000000000000000
Binary files a/tlatools/lib/aspectjweaver.jar and /dev/null differ
diff --git a/tlatools/lib/jpf-classes.jar b/tlatools/lib/jpf-classes.jar
new file mode 100644
index 0000000000000000000000000000000000000000..15a91af503b5aa6c7b016b932c227fb27c68fb76
Binary files /dev/null and b/tlatools/lib/jpf-classes.jar differ
diff --git a/tlatools/lib/jpf.jar b/tlatools/lib/jpf.jar
new file mode 100644
index 0000000000000000000000000000000000000000..28915b7cd4d47aa788cd776e4e1e4542a2263324
Binary files /dev/null and b/tlatools/lib/jpf.jar differ
diff --git a/tlatools/src-aj/META-INF/aop-ajc.xml b/tlatools/src-aj/META-INF/aop-ajc.xml
index efef8819df18c47c2226043f838929db52c92a08..c425d69c2e85a51b25349b374bea97f310a8b088 100644
--- a/tlatools/src-aj/META-INF/aop-ajc.xml
+++ b/tlatools/src-aj/META-INF/aop-ajc.xml
@@ -2,6 +2,7 @@
 <aspectj>
 
 	<aspects>
+		<aspect name="tlc2.tool.WorkerMonitorAspect"/>
 		<aspect name="tlc2.tool.distributed.RMIMethodMonitorAspect"/>
 		<aspect name="tlc2.tool.distributed.TLCServerMonitorAspect"/>
 	</aspects>
diff --git a/tlatools/src-aj/META-INF/aop.xml b/tlatools/src-aj/META-INF/aop.xml
index efef8819df18c47c2226043f838929db52c92a08..c425d69c2e85a51b25349b374bea97f310a8b088 100644
--- a/tlatools/src-aj/META-INF/aop.xml
+++ b/tlatools/src-aj/META-INF/aop.xml
@@ -2,6 +2,7 @@
 <aspectj>
 
 	<aspects>
+		<aspect name="tlc2.tool.WorkerMonitorAspect"/>
 		<aspect name="tlc2.tool.distributed.RMIMethodMonitorAspect"/>
 		<aspect name="tlc2.tool.distributed.TLCServerMonitorAspect"/>
 	</aspects>
diff --git a/tlatools/src-aj/tlc2/tool/WorkerMonitor.java b/tlatools/src-aj/tlc2/tool/WorkerMonitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8e57d5c41fe2846c05894110faebee9e967eb7d
--- /dev/null
+++ b/tlatools/src-aj/tlc2/tool/WorkerMonitor.java
@@ -0,0 +1,29 @@
+package tlc2.tool;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class WorkerMonitor {
+
+	private static final Set<ThreadListener> listeners = new HashSet<ThreadListener>();
+	
+	public static void addPerformanceResult(final Thread thread, final long runningTime) {
+		for (ThreadListener threadListener : listeners) {
+			threadListener.terminated(thread, runningTime);
+		}
+	}
+
+	public static void addThreadListener(ThreadListener threadListener) {
+		listeners.add(threadListener);
+	}
+	
+	
+	/**
+	 * A ThreadListener is notified of when the Worker thread terminates. The
+	 * notification includes the execution time of the thread.
+	 */
+	public static interface ThreadListener {
+
+		void terminated(final Thread thread, final long runningTime);
+	}
+}
diff --git a/tlatools/src-aj/tlc2/tool/WorkerMonitorAspect.aj b/tlatools/src-aj/tlc2/tool/WorkerMonitorAspect.aj
new file mode 100644
index 0000000000000000000000000000000000000000..7835e4a074a32e54fc1b7866c37b32f8afec3a4a
--- /dev/null
+++ b/tlatools/src-aj/tlc2/tool/WorkerMonitorAspect.aj
@@ -0,0 +1,27 @@
+package tlc2.tool;
+
+
+public aspect WorkerMonitorAspect perthis(callToRunMethod()) {
+	
+	private long threadStartTime, threadEndTime;
+	
+	pointcut callToRunMethod() : 
+		   execution(* tlc2.tool.Worker.run(..));
+	
+	before(): (callToRunMethod()) {
+		threadStartTime = System.currentTimeMillis();
+	}
+
+	after(): (callToRunMethod()) {
+		threadEndTime = System.currentTimeMillis();
+		WorkerMonitor.addPerformanceResult((Worker) thisJoinPoint.getTarget(), (threadEndTime - threadStartTime));
+	}
+//	
+//	pointcut callToSetUpMethod() :
+//		execution(* tlc2.tool.liveness.MultiThreadedSpecTest.setUp());
+//	
+//	before(): (callToSetUpMethod()) {
+//		Object target = thisJoinPoint.getTarget();
+//		System.out.println("SetUp pc: " + target);
+//	}
+}
diff --git a/tlatools/src/tlc2/TLCGlobals.java b/tlatools/src/tlc2/TLCGlobals.java
index cf5f8dac80578733bf10f0c5a45799e116df0934..93f581508e6b3b8a321b2369ff87bc3ab2f14920 100644
--- a/tlatools/src/tlc2/TLCGlobals.java
+++ b/tlatools/src/tlc2/TLCGlobals.java
@@ -26,6 +26,12 @@ public class TLCGlobals
 
     // Number of concurrent workers
     private static int numWorkers = 1;
+    
+	/**
+	 * Execute liveness checking when any of the disk graphs' size has increased
+	 * exceeding the threshold (10% by default).
+	 */
+    public static double livenessThreshold = 0.1d;
 
     public synchronized static void setNumWorkers(int n)
     {
diff --git a/tlatools/src/tlc2/tool/AbstractChecker.java b/tlatools/src/tlc2/tool/AbstractChecker.java
index 4b57996dd89e798125e440115debd50e9e00a65f..cac02087403e4bc837d1ec2df70ee62e1aac834e 100644
--- a/tlatools/src/tlc2/tool/AbstractChecker.java
+++ b/tlatools/src/tlc2/tool/AbstractChecker.java
@@ -29,10 +29,9 @@ import util.FilenameToStream;
  */
 public abstract class AbstractChecker implements Cancelable
 {
-    protected static final boolean LIVENESS_STATS = Boolean.getBoolean(Liveness.class.getPackage().getName() + ".statistics");
+	protected static final boolean LIVENESS_STATS = Boolean.getBoolean(Liveness.class.getPackage().getName() + ".statistics");
 	
     // SZ Mar 9, 2009: static modifier removed
-    protected long nextLiveCheck;
     protected AtomicLong numOfGenStates;
     protected TLCState predErrState;
     protected TLCState errState;
@@ -82,11 +81,6 @@ public abstract class AbstractChecker implements Cancelable
         // moved to file utilities
         this.metadir = FileUtil.makeMetaDir(specDir, fromChkpt);
         
-        // The number of states generated before the first liveness check is
-        // performed.  This value of 1000 sounds low, but since the value is
-        // doubled after each check up to a maximum of 640K (a number embedded
-        // in several places in the code), it probably doesn't much matter.
-        this.nextLiveCheck = 1000;
         this.numOfGenStates = new AtomicLong(0);
         this.errState = null;
         this.predErrState = null;
@@ -249,12 +243,9 @@ public abstract class AbstractChecker implements Cancelable
         // while (true) {
         while (!this.cancellationFlag)
         {
-            if (TLCGlobals.doCheckPoint())
+            if (!this.doPeriodicWork())
             {
-                if (!this.doPeriodicWork())
-                {
-                    return false;
-                }
+                return false;
             }
             synchronized (this)
             {
diff --git a/tlatools/src/tlc2/tool/DFIDModelChecker.java b/tlatools/src/tlc2/tool/DFIDModelChecker.java
index de5506dcbace63b4a07121f0ce173b2d2bdc9fd0..6cf83959cfe510fa255c5168eafb90180dc4e0f2 100644
--- a/tlatools/src/tlc2/tool/DFIDModelChecker.java
+++ b/tlatools/src/tlc2/tool/DFIDModelChecker.java
@@ -618,36 +618,34 @@ public class DFIDModelChecker extends AbstractChecker
         synchronized (this.theFPSet)
         {
             // Run liveness checking, if needed:
-            long stateNum = this.theFPSet.size();
-            boolean doCheck = this.checkLiveness && (stateNum >= nextLiveCheck);
-            if (doCheck)
+            if (this.checkLiveness)
             {
-                MP.printMessage(EC.TLC_CHECKING_TEMPORAL_PROPS, new String[] {"current", Long.toString(stateNum)});
-                if (!liveCheck.check())
+                if (!liveCheck.check(false))
                 {
                     return false;
                 }
-                nextLiveCheck = (stateNum < 600000) ? stateNum * 2 : stateNum + 200000;
             }
 
-            // Checkpoint:
-            MP.printMessage(EC.TLC_CHECKPOINT_START, this.metadir);
-            // start checkpointing:
-            this.theFPSet.beginChkpt();
-            if (this.checkLiveness)
-            {
-                liveCheck.beginChkpt();
-            }
-            UniqueString.internTbl.beginChkpt(this.metadir);
-
-            // Commit checkpoint:
-            this.theFPSet.commitChkpt();
-            if (this.checkLiveness)
-            {
-                liveCheck.commitChkpt();
+            if (TLCGlobals.doCheckPoint()) {
+            	// Checkpoint:
+            	MP.printMessage(EC.TLC_CHECKPOINT_START, this.metadir);
+            	// start checkpointing:
+            	this.theFPSet.beginChkpt();
+            	if (this.checkLiveness)
+            	{
+            		liveCheck.beginChkpt();
+            	}
+            	UniqueString.internTbl.beginChkpt(this.metadir);
+            	
+            	// Commit checkpoint:
+            	this.theFPSet.commitChkpt();
+            	if (this.checkLiveness)
+            	{
+            		liveCheck.commitChkpt();
+            	}
+            	UniqueString.internTbl.commitChkpt(this.metadir);
+            	MP.printMessage(EC.TLC_CHECKPOINT_END);
             }
-            UniqueString.internTbl.commitChkpt(this.metadir);
-            MP.printMessage(EC.TLC_CHECKPOINT_END);
         }
         return true;
     }
diff --git a/tlatools/src/tlc2/tool/ModelChecker.java b/tlatools/src/tlc2/tool/ModelChecker.java
index 3db3f98192e99245b5e31b837f6167a0945ec055..8b31f20f14163e6bbe92d7087d46fb752a7bf5a6 100644
--- a/tlatools/src/tlc2/tool/ModelChecker.java
+++ b/tlatools/src/tlc2/tool/ModelChecker.java
@@ -648,39 +648,40 @@ public class ModelChecker extends AbstractChecker
         if (this.theStateQueue.suspendAll())
         {
             // Run liveness checking, if needed:
-            long stateNum = this.theFPSet.size();
-            boolean doCheck = this.checkLiveness && (stateNum >= nextLiveCheck);
-            if (doCheck)
+            if (this.checkLiveness)
             {
-				MP.printMessage(EC.TLC_CHECKING_TEMPORAL_PROPS, new String[] { "current", Long.toString(stateNum) });
-                if (!liveCheck.check())
+                if (!liveCheck.check(false))
                     return false;
-                nextLiveCheck = (stateNum <= 640000) ? stateNum * 2 : stateNum + 640000;
             }
 
-            // Checkpoint:
-            MP.printMessage(EC.TLC_CHECKPOINT_START, this.metadir);
-
-            // start checkpointing:
-            this.theStateQueue.beginChkpt();
-            this.trace.beginChkpt();
-            this.theFPSet.beginChkpt();
-            this.theStateQueue.resumeAll();
-            UniqueString.internTbl.beginChkpt(this.metadir);
-            if (this.checkLiveness)
-            {
-                liveCheck.beginChkpt();
-            }
-            // commit checkpoint:
-            this.theStateQueue.commitChkpt();
-            this.trace.commitChkpt();
-            this.theFPSet.commitChkpt();
-            UniqueString.internTbl.commitChkpt(this.metadir);
-            if (this.checkLiveness)
-            {
-                liveCheck.commitChkpt();
+            if (TLCGlobals.doCheckPoint()) {
+            	// Checkpoint:
+            	MP.printMessage(EC.TLC_CHECKPOINT_START, this.metadir);
+            	
+            	// start checkpointing:
+            	this.theStateQueue.beginChkpt();
+            	this.trace.beginChkpt();
+            	this.theFPSet.beginChkpt();
+            	this.theStateQueue.resumeAll();
+            	UniqueString.internTbl.beginChkpt(this.metadir);
+            	if (this.checkLiveness)
+            	{
+            		liveCheck.beginChkpt();
+            	}
+            	// commit checkpoint:
+            	this.theStateQueue.commitChkpt();
+            	this.trace.commitChkpt();
+            	this.theFPSet.commitChkpt();
+            	UniqueString.internTbl.commitChkpt(this.metadir);
+            	if (this.checkLiveness)
+            	{
+            		liveCheck.commitChkpt();
+            	}
+            	MP.printMessage(EC.TLC_CHECKPOINT_END);
+            } else {
+				// Just resume worker threads when checkpointing is skipped
+            	this.theStateQueue.resumeAll();
             }
-            MP.printMessage(EC.TLC_CHECKPOINT_END);
         }
         return true;
     }
diff --git a/tlatools/src/tlc2/tool/Worker.java b/tlatools/src/tlc2/tool/Worker.java
index 698a83d6897bb634d72c5094b29ac083234a1421..3b98529ead182a74fc13c6b90bf1f0f5fc473a86 100644
--- a/tlatools/src/tlc2/tool/Worker.java
+++ b/tlatools/src/tlc2/tool/Worker.java
@@ -13,11 +13,11 @@ import tlc2.util.ObjLongTable;
 import tlc2.value.Value;
 
 public class Worker extends IdThread implements IWorker {
+	
 	/**
-   * Multi-threading helps only when running on multiprocessors. TLC
-   * can pretty much eat up all the cycles of a processor running
-   * single threaded.  We expect to get linear speedup with respect
-   * to the number of processors.
+	 * Multi-threading helps only when running on multiprocessors. TLC can
+	 * pretty much eat up all the cycles of a processor running single threaded.
+	 * We expect to get linear speedup with respect to the number of processors.
 	 */
 	private ModelChecker tlc;
 	private IStateQueue squeue;
@@ -72,15 +72,16 @@ public class Worker extends IdThread implements IWorker {
 					this.squeue.finishAll();
 					return;
 				}
-	if (this.tlc.doNext(curState, this.astCounts)) return;
-				}
+				if (this.tlc.doNext(curState, this.astCounts))
+					return;
 			}
-    catch (Throwable e) {
+		} catch (Throwable e) {
 			// Something bad happened. Quit ...
 			// Assert.printStack(e);
 			synchronized (this.tlc) {
 				if (this.tlc.setErrState(curState, null, true)) {
-	    MP.printError(EC.GENERAL, e);  // LL changed call 7 April 2012
+					MP.printError(EC.GENERAL, e); // LL changed call 7 April
+													// 2012
 				}
 				this.squeue.finishAll();
 				this.tlc.notify();
@@ -88,5 +89,4 @@ public class Worker extends IdThread implements IWorker {
 			return;
 		}
 	}
-
 }
diff --git a/tlatools/src/tlc2/tool/fp/FPSetStatistic.java b/tlatools/src/tlc2/tool/fp/FPSetStatistic.java
index f78dc084c3b98c7bc416c550a805b685ca5ca4c0..bec95090adc5a9348f2f646c9900bec161cdd8e9 100644
--- a/tlatools/src/tlc2/tool/fp/FPSetStatistic.java
+++ b/tlatools/src/tlc2/tool/fp/FPSetStatistic.java
@@ -1,6 +1,8 @@
 // Copyright (c) 2012 Markus Alexander Kuppe. All rights reserved.
 package tlc2.tool.fp;
 
+import java.io.IOException;
+
 public interface FPSetStatistic {
 
 	/**
@@ -118,4 +120,9 @@ public interface FPSetStatistic {
 	 * @return DiskFPSet#forceFlush();
 	 */
 	void forceFlush();
+	
+	/**
+	 * @see DiskFPSet#checkInvariant()
+	 */
+	boolean checkInvariant() throws IOException;
 }
diff --git a/tlatools/src/tlc2/tool/fp/LSBDiskFPSet.java b/tlatools/src/tlc2/tool/fp/LSBDiskFPSet.java
index f4d8f9f86abc0cba8ec4a0ee8a1a141782eeb787..cc84b78fa149cdeee2dfbcd3bc27a3288526aabb 100644
--- a/tlatools/src/tlc2/tool/fp/LSBDiskFPSet.java
+++ b/tlatools/src/tlc2/tool/fp/LSBDiskFPSet.java
@@ -39,6 +39,19 @@ public class LSBDiskFPSet extends HeapBasedDiskFPSet {
 			int cnt = (int) tblCnt.get();
 			Assert.check(cnt > 0, EC.GENERAL);
 			
+			// Why not sort this.tbl in-place rather than doubling memory
+			// requirements by copying to clone array and subsequently sorting it?
+			// - disk written fps are marked disk written by changing msb to 1
+			// - next time such a fp from the in-memory this.tlb is converted on the
+			// fly back and again used to do an in-memory lookup
+			//
+			// - this.tbl bucket assignment (hashing) is done on least significant bits,
+			// which makes in-place sort with overlay index infeasible
+			// - erasing this.tbl means we will loose the in-memory cache completely until it fills up again
+			// - new fps overwrite disk flushed fps in-memory
+			// see MSBDiskFPSet for an implementation that doesn't have the
+			// requirement to sort in a clone array.
+	
 			// copy table contents into a buffer array buff; do not erase tbl
 			buff = new long[cnt];
 			int idx = 0;
diff --git a/tlatools/src/tlc2/tool/fp/MSBDiskFPSet.java b/tlatools/src/tlc2/tool/fp/MSBDiskFPSet.java
index d78d75bb5cc421e9a85f21964b311dd21d18ea8a..d5ceafdb440926b49fa45658913781f08fecb4af 100644
--- a/tlatools/src/tlc2/tool/fp/MSBDiskFPSet.java
+++ b/tlatools/src/tlc2/tool/fp/MSBDiskFPSet.java
@@ -71,17 +71,6 @@ public class MSBDiskFPSet extends HeapBasedDiskFPSet {
 		 */
 		protected void prepareTable() {
 			
-			// Why not sort this.tbl in-place rather than doubling memory
-			// requirements by copying to clone array and subsequently sorting it?
-			// - disk written fps are marked disk written by changing msb to 1
-			// - next time such a fp from the in-memory this.tlb is converted on the
-			// fly back and again used to do an in-memory lookup
-			//
-			// - this.tbl bucket assignment (hashing) is done on least significant bits,
-			// which makes in-place sort with overlay index infeasible
-			// - erasing this.tbl means we will loose the in-memory cache completely until it fills up again
-			// - new fps overwrite disk flushed fps in-memory
-	
 			// copy table contents into a buffer array buff; do not erase tbl, but 1
 			// msb of each fp to indicate it has been flushed to disk
 			for (int j = 0; j < tbl.length; j++) {
@@ -111,10 +100,18 @@ public class MSBDiskFPSet extends HeapBasedDiskFPSet {
 			final long buffLen = tblCnt.get();
 			final TLCIterator itr = new TLCIterator(tbl);
 
-			// Precompute the maximum value of the new file
-			long maxVal = itr.getLast();
+			// Precompute the maximum value of the new file.
+			// If this isn't the first merge, the index has
+			// the last element of the disk file. In that case
+			// the new maxVal is the larger element of the two
+			// in-memory and on-disk elements.
+			// The largest on-disk element is passed to the
+			// iterator as a lower bound.
+			long maxVal;
 			if (index != null) {
-				maxVal = Math.max(maxVal, index[index.length - 1]);
+				maxVal = itr.getLast(index[index.length - 1]);
+			} else {
+				maxVal = itr.getLast();
 			}
 	
 			int indexLen = calculateIndexLen(buffLen);
@@ -152,6 +149,7 @@ public class MSBDiskFPSet extends HeapBasedDiskFPSet {
 					if (value == fp) {
 						Assert.check(false, EC.TLC_FP_VALUE_ALREADY_ON_DISK,
 								String.valueOf(value));
+						
 					}
 					writeFP(outRAF, fp);
 					// we used one fp up, thus move to next one
@@ -287,13 +285,77 @@ public class MSBDiskFPSet extends HeapBasedDiskFPSet {
 			return result;
 		}
 
+		/**
+		 * @param lowBound
+		 *            Stop searching for the last element if no element is
+		 *            larger than lowBound
+		 * @return The last element in the iteration that is larger than lowBound
+		 * @exception NoSuchElementException
+		 *                if iteration is empty.
+		 *                <p>
+		 *                Pre-condition: Each bucket is sorted in ascending
+		 *                order. on-disk fingerprints don't adhere to the
+		 *                ascending order though!
+		 */
+		public long getLast(final long lowBound) {
+			int len = buff.length;
+
+			// Walk from the end of buff to the beginning. Each bucket that is
+			// found and non-null (null if no fingerprint for such an index has
+			// been added to the DiskFPSet) is checked for a valid fingerprint.
+			// A fp is valid iff it is larger zero. A zero fingerprint slot
+			// indicates an unoccupied slot, while a negative one corresponds to
+			// a fp that has already been flushed to disk.
+			while (len > 0) {
+				long[] bucket = buff[--len];
+
+				// Find last element > 0 in bucket (negative elements have already
+				// been flushed to disk, zero indicates an unoccupied slot).
+				if (bucket != null) {
+					for (int i = bucket.length - 1; i >= 0; i--) {
+						final long fp = bucket[i];
+						// unused slot
+						if (fp == 0) {
+							continue;
+						}
+						// in-memory fingerprint
+						if (fp > 0) {
+							if (fp < lowBound) {
+								// smaller lowBound
+								return lowBound;
+							} else {
+								// larger or equal lowBound
+								return fp;
+							}
+						}
+						// Cannot take on-disk fingerprints (negative ones) into
+						// account. They don't adhere to the precondition that
+						// the bucket is sorted. The bucket is logically sorted
+						// only for in-memory fingerprints.
+					}
+				}
+			}
+			// At this point we have scanned the complete buff, but haven't
+			// found a single fingerprint that hasn't been flushed to disk
+			// already.
+			throw new NoSuchElementException();
+		}
+
 		/**
 		 * @return The last element in the iteration.
 	     * @exception NoSuchElementException if iteration is empty.
+	     * 
+	     * Pre-condition: Each bucket is sorted in ascending order!
 		 */
 		public long getLast() {
-			int len = buff.length - 1;
-			long[] bucket = buff[len];
+			/*
+			 * Tempting to delegate to getLast(Long.MAX_VALUE). However,
+			 * getLast() could not throw a NoSuchElementException when the
+			 * value returned is Long.MAX_VALUE. It could be a valid value, but
+			 * it might as well be the cutOff.
+			 */
+			
+			int len = buff.length;
 
 			// Walk from the end of buff to the beginning. Each bucket that is
 			// found and non-null (null if no fingerprint for such an index has
@@ -302,7 +364,7 @@ public class MSBDiskFPSet extends HeapBasedDiskFPSet {
 			// indicates an unoccupied slot, while a negative one corresponds to
 			// a fp that has already been flushed to disk.
 			while (len > 0) {
-				bucket = buff[--len];
+				long[] bucket = buff[--len];
 
 				// Find last element > 0 in bucket (negative elements have already
 				// been flushed to disk, zero indicates an unoccupied slot).
diff --git a/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXBean.java b/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXBean.java
index 056e23019c761bc515a5dcf90c22bbf7f3b805a3..6ca77dfc1cfce40e641db52692cd7bb50893ccd9 100644
--- a/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXBean.java
+++ b/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXBean.java
@@ -1,6 +1,8 @@
 // Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
 package tlc2.tool.fp.management;
 
+import java.io.IOException;
+
 import tlc2.tool.fp.DiskFPSet;
 import tlc2.tool.fp.FPSet;
 
@@ -111,4 +113,9 @@ public interface DiskFPSetMXBean {
 	 * @see DiskFPSet#forceFlush()
 	 */
 	void forceFlush();
+	
+	/**
+	 * @see DiskFPSet#checkInvariant()
+	 */
+	boolean checkInvariant() throws IOException;
 }
diff --git a/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXWrapper.java b/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXWrapper.java
index 577a145cc552f2c5c4bce4807d8ced940643488e..74d097f8b843f17229672f6ef8cd2bf250457dcc 100644
--- a/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXWrapper.java
+++ b/tlatools/src/tlc2/tool/fp/management/DiskFPSetMXWrapper.java
@@ -1,6 +1,8 @@
 // Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
 package tlc2.tool.fp.management;
 
+import java.io.IOException;
+
 import javax.management.NotCompliantMBeanException;
 
 import tlc2.tool.fp.FPSetStatistic;
@@ -189,4 +191,11 @@ public class DiskFPSetMXWrapper extends TLCStandardMBean implements DiskFPSetMXB
 	public void forceFlush() {
 		fpset.forceFlush();
 	}
+
+	/* (non-Javadoc)
+	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#checkInvariant()
+	 */
+	public boolean checkInvariant() throws IOException {
+		return fpset.checkInvariant();
+	}
 }
diff --git a/tlatools/src/tlc2/tool/liveness/AbstractDiskGraph.java b/tlatools/src/tlc2/tool/liveness/AbstractDiskGraph.java
index 7eea7644373f8d157d83935c1c479154e690dbd2..b2865fbd0a95d58389e5a29af446c35719fd8e45 100644
--- a/tlatools/src/tlc2/tool/liveness/AbstractDiskGraph.java
+++ b/tlatools/src/tlc2/tool/liveness/AbstractDiskGraph.java
@@ -84,6 +84,8 @@ public abstract class AbstractDiskGraph {
 
 	private final IBucketStatistics outDegreeGraphStats;
 
+	private long sizeAtCheck = 1; // initialize with 1 to avoid div by zero
+
 	public AbstractDiskGraph(String metadir, int soln, IBucketStatistics graphStats) throws IOException {
 		this.metadir = metadir;
 		this.outDegreeGraphStats = graphStats;
@@ -259,6 +261,15 @@ public abstract class AbstractDiskGraph {
 	 */
 	public abstract long size();
 	
+	
+	public long getSizeAtLastCheck() {
+		return sizeAtCheck;
+	}
+
+	public void recordSize() {
+		this.sizeAtCheck = size();
+	}
+	
 	/**
 	 * Only useful for debugging.
 	 * 
@@ -393,12 +404,10 @@ public abstract class AbstractDiskGraph {
 			tidx = nodeRAF.readInt();
 		}
 
-		@Override
 		public String toString() {
 			return "NodeRAFRecord [fp=" + fp + ", tidx=" + tidx + "]";
 		}
 
-		@Override
 		public int hashCode() {
 			final int prime = 31;
 			int result = 1;
@@ -408,7 +417,6 @@ public abstract class AbstractDiskGraph {
 			return result;
 		}
 
-		@Override
 		public boolean equals(Object obj) {
 			if (this == obj)
 				return true;
diff --git a/tlatools/src/tlc2/tool/liveness/ILiveCheck.java b/tlatools/src/tlc2/tool/liveness/ILiveCheck.java
index 3284edf928beb1ed8f68ed62b0335473456c97e5..171a00672f42ed8b829429dc06ea9a16959de998 100644
--- a/tlatools/src/tlc2/tool/liveness/ILiveCheck.java
+++ b/tlatools/src/tlc2/tool/liveness/ILiveCheck.java
@@ -23,10 +23,17 @@ public interface ILiveCheck {
 	void addNextState(TLCState s0, long fp0, StateVec nextStates, LongVec nextFPs) throws IOException;
 	
 	/**
-	 * Check liveness properties for the current partial state graph. Returns
+	 * Check liveness properties for the current (potentially partial) state graph. Returns
 	 * true iff it finds no errors.
+	 * 
+	 * @param forceCheck
+	 *            Always checks liveness if true, otherwise heuristics about the
+	 *            partial graph are taken into account if it is worthwhile to
+	 *            check liveness.
+	 * @return true iff it finds no errors or if liveness has not been checked
+	 *         on the partial graph because it was deemed worthless.
 	 */
-	boolean check() throws Exception;
+	boolean check(boolean forceCheck) throws Exception;
 
 	/**
 	 * No states can be added with add*State once finalCheck has been called.
diff --git a/tlatools/src/tlc2/tool/liveness/LiveCheck.java b/tlatools/src/tlc2/tool/liveness/LiveCheck.java
index 56e00b2f396be72790e78b90af7175b069af6463..4aa5c699bbbef22f729027b8c661c26bd6daad1c 100644
--- a/tlatools/src/tlc2/tool/liveness/LiveCheck.java
+++ b/tlatools/src/tlc2/tool/liveness/LiveCheck.java
@@ -93,10 +93,31 @@ public class LiveCheck implements ILiveCheck {
 	}
 
 	/* (non-Javadoc)
-	 * @see tlc2.tool.liveness.ILiveCheck#check()
+	 * @see tlc2.tool.liveness.ILiveCheck#check(boolean)
 	 */
-	public boolean check() throws Exception {
-		return check(false);
+	public boolean check(boolean forceCheck) throws Exception {
+		if (forceCheck) {
+			return check0(false);
+		}
+		for (int i = 0; i < checker.length; i++) {
+			// If anyone of the disk graphs has increased by the given
+			// percentage, run liveness checking. This is the best heuristic I
+			// can come up with quickly.
+			//
+			// TODO Alternatively the level could be taken
+			// into account. Unless the level (height) of the graph increases, 
+			// no new cycle won't be found anyway. All other aspects of liveness
+			// checking are checked as part of regular safety checking.
+			final AbstractDiskGraph diskGraph = checker[i].getDiskGraph();
+			final long sizeAtLastCheck = diskGraph.getSizeAtLastCheck();
+			final long sizeCurrently = diskGraph.size();
+			final double delta = (sizeCurrently - sizeAtLastCheck) / (sizeAtLastCheck * 1.d);
+			if (delta > TLCGlobals.livenessThreshold) {
+				return check0(false);
+			}
+		}
+		
+		return true;
 	}
 	
 	/* (non-Javadoc)
@@ -105,10 +126,23 @@ public class LiveCheck implements ILiveCheck {
 	public boolean finalCheck() throws InterruptedException, IOException {
 		// Do *not* re-create the nodePtrTable after the check which takes a
 		// while for larger disk graphs.
-		return check(true);
+		return check0(true);
 	}
 	
-	private boolean check(final boolean finalCheck) throws InterruptedException, IOException {
+	/**
+	 * @param finalCheck
+	 *            If the internal nodePtrTbl should be restored for a subsequent
+	 *            liveness check. If this is the final/last check, it's pointless
+	 *            to re-create the nodePtrTable.
+	 */
+	private boolean check0(final boolean finalCheck) throws InterruptedException, IOException {
+		long sum = 0L;
+		for (int i = 0; i < checker.length; i++) {
+			sum += checker[i].getDiskGraph().size();
+		}
+		MP.printMessage(EC.TLC_CHECKING_TEMPORAL_PROPS,
+				new String[] { "current", Long.toString(sum) });
+
 		// Copy the array of checkers into a concurrent-enabled queue
 		// that allows LiveWorker threads to easily get the next 
 		// LiveChecker to work on. We don't really need the FIFO
@@ -133,7 +167,7 @@ public class LiveCheck implements ILiveCheck {
 			LiveWorker worker = new LiveWorker(0, this, queue);
 			worker.run();
 		} else {
-			LiveWorker[] workers = new LiveWorker[wNum];
+			final LiveWorker[] workers = new LiveWorker[wNum];
 			for (int i = 0; i < wNum; i++) {
 				workers[i] = new LiveWorker(i, this, queue);
 				workers[i].start();
@@ -192,7 +226,8 @@ public class LiveCheck implements ILiveCheck {
 		final TLCState lastState = stateTrace.elementAt(stateTrace.size() - 1);
 		addNextState(lastState, lastState.fingerPrint(), new StateVec(0), new LongVec(0));
 		
-		if (!finalCheck()) { //HACK Calling finalCheck here to prevent code from re-creating the nodeptrtable from a non existant file.
+		// Do *not* re-create the nodePtrTbl when it is thrown away anyway.
+		if (!check0(true)) {
 			throw new LiveException();
 		}
 		
@@ -641,12 +676,17 @@ public class LiveCheck implements ILiveCheck {
 	// Intended to be used in unit tests only!!! This is not part of the API!!!
 	static class TestHelper {
 		
+		/*
+		 * - EWD840 (with tableau) spec with N = 11 and maxSetSize = 9.000.000 => 12GB nodes file, 46.141.438 distinct states
+		 * - EWD840 (with tableau) spec with N = 12 and maxSetSize = 9.000.000 => 56GB, 201.334.782 dist. states 
+		 */
+		
 		// The Eclipse Launch configuration has to set the working directory
 		// (Arguments tab) to the parent directory of the folder containing the
 		// nodes_* and ptrs_* files. The parent folder has to contain the spec
 		// and config file both named "MC".
 		// metadir is the the name of the folder with the nodes_* and ptrs_*
-		// relative to the parent directory. It does *not* need to contain the
+		// relative to the parent directory. The directory does *not* need to contain the
 		// backing file of the fingerprint set or the state queue files.
 		public static ILiveCheck recreateFromDisk(final String path) throws Exception {
 			// Don't know with which Polynomial the FP64 has been initialized, but
@@ -661,6 +701,11 @@ public class LiveCheck implements ILiveCheck {
 	        final Tool tool = new Tool("", "MC", "MC", new SimpleFilenameToStream());
 	        tool.init(true, null);
 	        
+			// Initialize tool's actions explicitly. LiveCheck#printTrace is
+			// going to access the actions and fails with a NPE unless
+			// initialized.
+	        tool.getActions();
+	        
 			final ILiveCheck liveCheck = new LiveCheck(tool, null, path, new DummyBucketStatistics());
 			
 			// Calling recover requires a .chkpt file to be able to re-create the
diff --git a/tlatools/src/tlc2/tool/liveness/LiveCheck1.java b/tlatools/src/tlc2/tool/liveness/LiveCheck1.java
index ac8772513c9c5e7baa2a3ba09e7a949280c4693e..d09308dc91ab06ba25f5c6faa7d55649b96854d0 100644
--- a/tlatools/src/tlc2/tool/liveness/LiveCheck1.java
+++ b/tlatools/src/tlc2/tool/liveness/LiveCheck1.java
@@ -442,7 +442,7 @@ public class LiveCheck1 implements ILiveCheck {
 	 * "bad" cycle. A "bad" cycle gives rise to a violation of liveness
 	 * property.
 	 */
-	public synchronized boolean check() {
+	public synchronized boolean check(boolean forceCheck) {
 		int slen = solutions.length;
 		if (slen == 0) {
 			return true;
@@ -910,7 +910,7 @@ public class LiveCheck1 implements ILiveCheck {
 	 * @see tlc2.tool.liveness.ILiveCheck#finalCheck()
 	 */
 	public boolean finalCheck() throws Exception {
-		return check();
+		return check(true);
 	}
 
 	/* (non-Javadoc)
diff --git a/tlatools/src/tlc2/tool/liveness/LiveWorker.java b/tlatools/src/tlc2/tool/liveness/LiveWorker.java
index 27589913625aac0d7be16ac756a7662381a76d27..00dffb898622c0ae567a23fb182cea525eb68901 100644
--- a/tlatools/src/tlc2/tool/liveness/LiveWorker.java
+++ b/tlatools/src/tlc2/tool/liveness/LiveWorker.java
@@ -700,6 +700,10 @@ public class LiveWorker extends IdThread {
 					}
 				}
 				this.dg.destroyCache();
+				// Record the size of the disk graph at the time its checked. This
+				// information is later used to decide if it it makes sense to
+				// run the next check on the larger but still *partial* graph.
+				this.dg.recordSize();
 			}
 		} catch (Exception e) {
 			MP.printError(EC.GENERAL, "checking liveness", e); // LL changed
diff --git a/tlatools/src/tlc2/tool/liveness/NoOpLiveCheck.java b/tlatools/src/tlc2/tool/liveness/NoOpLiveCheck.java
index 9e4d05c0f9972ecbbd6ca4db0642fab5c6fc4fac..5466402f300ba70f4faf0ad69f290186d745f80c 100644
--- a/tlatools/src/tlc2/tool/liveness/NoOpLiveCheck.java
+++ b/tlatools/src/tlc2/tool/liveness/NoOpLiveCheck.java
@@ -60,9 +60,9 @@ public class NoOpLiveCheck implements ILiveCheck {
 	}
 
 	/* (non-Javadoc)
-	 * @see tlc2.tool.liveness.ILiveCheck#check()
+	 * @see tlc2.tool.liveness.ILiveCheck#check(boolean)
 	 */
-	public boolean check() throws Exception {
+	public boolean check(boolean forceCheck) throws Exception {
 		return true;
 	}
 
diff --git a/tlatools/src/tlc2/tool/queue/StateQueue.java b/tlatools/src/tlc2/tool/queue/StateQueue.java
index b55f1eaee48a00a6121cc6cd79fdea119fec7fb6..0d151ecadd933e9a1733edabc6912a773a1762fe 100644
--- a/tlatools/src/tlc2/tool/queue/StateQueue.java
+++ b/tlatools/src/tlc2/tool/queue/StateQueue.java
@@ -18,7 +18,7 @@ import util.Assert;
  * 
  */
 // TODO-MAK - Why do consumer/producer game on StateQueue when workers could
-// maintaine thread local StateQueue until it gets empty?
+// maintain thread local StateQueue until it gets empty?
 public abstract class StateQueue implements IStateQueue {
 	/**
 	 * In model checking, this is the sequence of states waiting to be explored
@@ -26,7 +26,7 @@ public abstract class StateQueue implements IStateQueue {
 	 */
 	protected long len = 0; // the queue length
 	private int numWaiting = 0; // the number of waiting threads
-	private boolean finish = false; // terminate
+	private volatile boolean finish = false; // terminate
 	/**
 	 * Signals {@link Worker} that checkpointing is going happen next.
 	 */
@@ -140,6 +140,11 @@ public abstract class StateQueue implements IStateQueue {
 	 * @return true if states are available in the queue.
 	 */
 	private final boolean isAvail() {
+		/*
+		 * isAvail is only called from within sDequeue() and sDequeue(..) and
+		 * thus is always synchronized on this.
+		 */
+		
 		if (this.finish) {
 			return false;
 		}
@@ -179,7 +184,22 @@ public abstract class StateQueue implements IStateQueue {
 	 */
 	public synchronized void finishAll() {
 		this.finish = true;
+		// Notify all other worker threads.
 		this.notifyAll();
+		// Need to wake main thread that waits (mu.wait()) to suspend access to
+		// the squeue (see suspendAll). The main thread might attempt to do its
+		// periodic work (tlc2.tool.ModelChecker.doPeriodicWork()) the moment
+		// all worker threads finish. Since suspendAll assumes the main thread
+		// is woken up (potentially) multiple times from sleeping indefinitely
+		// in the while loop before it finally returns after locking the
+		// StateQueue, we have to live up to this assumption.
+		//
+		// synchronized(this.mu) does not block when the main thread waits on
+		// this.mu in suspend all. We merely have to follow proper thread access.
+		synchronized (this.mu) {
+			// Technically notify() would do.
+			this.mu.notify();
+		}
 	}
 
 	/* (non-Javadoc)
@@ -194,11 +214,39 @@ public abstract class StateQueue implements IStateQueue {
 			this.stop = true;
 			needWait = needsWaiting();
 		}
+		// Wait for all worker threads to stop.
 		while (needWait) {
 			synchronized (this.mu) {
 				try {
+					// finishAll & suspendAll race:
+					//
+					// suspendAll from main is on the heels of finishAll, but
+					// not quite as fast. SuspendAll's synchronized(this.mu)
+					// is executed one clock tick after finishAll's thus waiting
+					// for finishAll() to notify all waiters of this.mu.
+					// With main being the only potential waiter in the system
+					// nobody gets notified and the lock on this released
+					// subsequently.
+					// Now it's suspendAll's turn. It acquires the lock on
+					// this.mu and immediately after goes to wait on it
+					// (this.mu) to be waken by worker threads eventually.
+					// Unfortunately, there are none left in the system. All
+					// have long finishedAll.
+					//
+					// The fix is to check the this.finish variable one more
+					// time directly after suspendAll acquires the lock this.mu,
+					// it checks if it still has to wait for workers. To make
+					// sure it reads the most recent value, it's declared
+					// volatile to establish a happens-before relation (since
+					// Java5's memory model) between workers and main. Otherwise
+					// the VM might decide to let main read a cached value of
+					// false of this.finish.
+					if (this.finish) {
+						return false;
+					}
 					// waiting here assumes that subsequently a worker
-					// is going to wake us up by calling isAvail()
+					// is going to wake us up by calling isAvail() or
+					// this.mu.notify*()
 					this.mu.wait();
 				} catch (Exception e) {
 					MP.printError(EC.GENERAL, "waiting for a worker to wake up", e);  // LL changed call 7 April 2012
diff --git a/tlatools/test-long/tlc2/tool/liveness/MultiThreadedSpecTest.java b/tlatools/test-long/tlc2/tool/liveness/MultiThreadedSpecTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2e0f4dcf5db43857d0b3340afadda9b23bfae0a
--- /dev/null
+++ b/tlatools/test-long/tlc2/tool/liveness/MultiThreadedSpecTest.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Microsoft Research. All rights reserved. 
+ *
+ * The MIT License (MIT)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy 
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software. 
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Contributors:
+ *   Markus Alexander Kuppe - initial API and implementation
+ ******************************************************************************/
+
+package tlc2.tool.liveness;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import tlc2.TLCGlobals;
+import tlc2.output.EC;
+import tlc2.tool.WorkerMonitor;
+
+/**
+ * This test takes about four minutes with 32 cores on an EC2 cr1.8xlarge instance.
+ * On a Thinkpad T430s it takes eight times as long and uses up 4GB of memory (see customBuild.xml).
+ * 
+ * The purpose of this test is to establish a thread contention baseline that TLC shows for
+ * liveness checking (with and without tableaux). More precisely the time each TLC worker
+ * thread spends in the WAITING and BLOCKED state must not exceed more than waitedRatio and
+ * blockedRatio. The current values for waitedRatio and blockedRatio have been obtained empirically.
+ */
+public abstract class MultiThreadedSpecTest extends ModelCheckerTestCase {
+
+	private final String statesGenerated;
+	private final String distinctStatesGenerated;
+	private final List<PerformanceResult> performanceResults = new ArrayList<PerformanceResult>();
+	private final CountDownLatch latch = new CountDownLatch(getNumberOfThreads());
+	private final double waitedRatio;
+	private final double blockedRatio;
+	
+	public MultiThreadedSpecTest(String spec, String path, String statesGenerated, String distinctStatesGenerated, double blockedRatio, double waitedRatio) {
+		super(spec, path);
+		this.statesGenerated = statesGenerated;
+		this.distinctStatesGenerated = distinctStatesGenerated;
+		this.blockedRatio = blockedRatio;
+		this.waitedRatio = waitedRatio;
+	}
+
+	public MultiThreadedSpecTest(String spec, String path, String[] extraArguments, String statesGenerated, String distinctStatesGenerated, double blockedRatio, double waitedRatio) {
+		super(spec, path, extraArguments);
+		this.statesGenerated = statesGenerated;
+		this.distinctStatesGenerated = distinctStatesGenerated;
+		this.blockedRatio = blockedRatio;
+		this.waitedRatio = waitedRatio;
+	}
+
+	public void testSpec() throws BrokenBarrierException, InterruptedException, TimeoutException {
+		// ModelChecker has finished and generated the expected amount of states
+		assertTrue(recorder.recorded(EC.TLC_FINISHED));
+		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, statesGenerated, distinctStatesGenerated));
+		
+		// Assert it has found the temporal violation and also a counter example
+		assertTrue(recorder.recorded(EC.TLC_TEMPORAL_PROPERTY_VIOLATED));
+		assertTrue(recorder.recorded(EC.TLC_COUNTER_EXAMPLE));
+		
+		// Assert the error trace
+		assertTrue(recorder.recorded(EC.TLC_STATE_PRINT3));
+		
+		// Allow TLC worker threads to take 10 seconds to shutdown and report
+		// their PerformanceResults to us. TLC's master thread has no reason to
+		// wait for the final termination of all worker threads once it has
+		// received the signal from one of them. After all the VM itself is
+		// going to shutdown after TLC is done printing results.
+		latch.await(10, TimeUnit.SECONDS);
+
+		// Except as many results as we have started worker threads.
+		//
+		// If this assert fails, make sure that AspectJ is loaded and the
+		// WorkerMonitorAspect is woven. This is done automatically by the ant
+		// build (customBuild.xml) but not when this test is executed inside
+		// Eclipse. AJDT (the AspectJ development tools) should not be a general
+		// requirement to compile the tlatools/ project in Eclipse.
+		//
+		// If you ask why it uses AspectJ the first place... Rather than adding
+		// API to the TLC code making in more and more complex just to test its
+		// performance behavior, I deemed the extra test complexity caused by
+		// AspectJ acceptable. We trade less complexity in program code with
+		// higher complexity in test code.
+		//
+		// To run this test in Eclipse, install AJDT (http://eclipse.org/ajdt/),
+		// convert the tlatools/ project into an AspectJ project via the 
+		// Package Explorers context menu and add 
+		// "-javaagent:${project_loc:tlatools}/lib/aspectjweaver-1.8.5.jar" 
+		// as a program argument to your JUnit launch config.
+		//
+		// If you get some but not all results, it's most certainly unrelated to
+		// AspectJ and indicates a programming bug.
+		assertEquals("PerfResult size is 0? => Is AspectJ load time weaving enabled?", getNumberOfThreads(),
+				performanceResults.size());
+		
+		// None of the workers threads should have been blocked or waiting for
+		// more than 25%
+		for (PerformanceResult result : performanceResults) {
+			assertTrue(String.format("Blocked(%s): %.3f", result.getThreadName(), result.getBlockedRatio()),
+					result.getBlockedRatio() < blockedRatio);
+			assertTrue(String.format("Waiting(%s): %.3f", result.getThreadName(), result.getWaitedRatio()),
+					result.getWaitedRatio() < waitedRatio);
+		}
+	}
+	
+	public void setUp() {
+		// Set the threshold before TLC (periodically) checks liveness to
+		// the largest possible value. This essentially stops TLC from checking
+		// liveness during model checking and delays it until the end when one
+		// final liveness check is run. We only then get deterministic behavior
+		// needed by this test to e.g. check the number of states generated...
+		TLCGlobals.livenessThreshold = Double.MAX_VALUE;
+		
+		final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+		// Enable contention thread statistics to have the JVM measure
+		// BlockedTime and WaitedTime.
+		threadBean.setThreadContentionMonitoringEnabled(true);
+
+		// Register a listener hot for the termination of the TLC worker
+		// threads. 
+		// Using ThreadMXBean directly to lookup all threads after TLC has
+		// finished has the potential that the JVM deletes the worker threads
+		// before this test gets a chance to collect statistics.
+		WorkerMonitor.addThreadListener(new WorkerMonitor.ThreadListener() {
+			public synchronized void terminated(final Thread thread, final long runningTime) {
+				final ThreadInfo threadInfo = threadBean.getThreadInfo(thread.getId());
+				double d = threadInfo.getBlockedTime() / (runningTime * 1.0d);
+				double d2 = threadInfo.getWaitedTime() / (runningTime * 1.0d);
+				performanceResults.add(new PerformanceResult(thread.getName(), d, d2));
+				latch.countDown();
+			}
+		});
+		
+		super.setUp();
+	}
+	
+	protected int getNumberOfThreads() {
+		// Run this test with as many threads possible to hopefully spot concurrency issues.
+		return Runtime.getRuntime().availableProcessors();
+	}
+	
+	private static class PerformanceResult {
+
+		private final double blockedRatio;
+		private final double waitedRatio;
+		private final String threadName;
+
+		public PerformanceResult(String threadName, double blockedRatio, double waitedRatio) {
+			this.threadName = threadName;
+			this.blockedRatio = blockedRatio;
+			this.waitedRatio = waitedRatio;
+		}
+
+		public double getWaitedRatio() {
+			return waitedRatio;
+		}
+
+		public double getBlockedRatio() {
+			return blockedRatio;
+		}
+		
+		public String getThreadName() {
+			return threadName;
+		}
+	}
+}
diff --git a/tlatools/test-long/tlc2/tool/liveness/NoTableauSpecTest.java b/tlatools/test-long/tlc2/tool/liveness/NoTableauSpecTest.java
index d8ebe9d5cd49e9e1ef948838b5b5b8a4ee65b225..87779edbc369c33844c2c7f8da33fa437a98d23f 100644
--- a/tlatools/test-long/tlc2/tool/liveness/NoTableauSpecTest.java
+++ b/tlatools/test-long/tlc2/tool/liveness/NoTableauSpecTest.java
@@ -23,37 +23,11 @@
  * Contributors:
  *   Markus Alexander Kuppe - initial API and implementation
  ******************************************************************************/
-
 package tlc2.tool.liveness;
 
-import tlc2.output.EC;
-
-/**
- * This takes about four minutes with 32 cores on an EC2 cr1.8xlarge instance.
- * On a Thinkpad T430s it takes eight times as long.
- */
-public class NoTableauSpecTest extends ModelCheckerTestCase {
+public class NoTableauSpecTest extends MultiThreadedSpecTest {
 
 	public NoTableauSpecTest() {
-		super("MC", "VoteProof");
-	}
-	
-	public void testSpec() {
-		// ModelChecker has finished and generated the expected amount of states
-		assertTrue(recorder.recorded(EC.TLC_FINISHED));
-		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "137297983", "693930"));
-		
-		// Assert it has found the temporal violation and also a counter example
-		assertTrue(recorder.recorded(EC.TLC_TEMPORAL_PROPERTY_VIOLATED));
-		assertTrue(recorder.recorded(EC.TLC_COUNTER_EXAMPLE));
-		
-		// Assert the error trace
-		assertTrue(recorder.recorded(EC.TLC_STATE_PRINT3));
-	}
-
-	protected String getNumberOfThreads() {
-		// Run this test with as many threads possible to hopefully spot concurrency issues.
-		int availableProcessors = Runtime.getRuntime().availableProcessors();
-		return Integer.toString(availableProcessors);
+		super("MC", "VoteProof", "137297983", "693930", 0.25d, 0.25d);
 	}
 }
diff --git a/tlatools/test-long/tlc2/tool/liveness/TableauSpecTest.java b/tlatools/test-long/tlc2/tool/liveness/TableauSpecTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2789e1a5b8e91e542adddf8f6ac64fa0c3b58d5
--- /dev/null
+++ b/tlatools/test-long/tlc2/tool/liveness/TableauSpecTest.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Microsoft Research. All rights reserved. 
+ *
+ * The MIT License (MIT)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy 
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software. 
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Contributors:
+ *   Markus Alexander Kuppe - initial API and implementation
+ ******************************************************************************/
+package tlc2.tool.liveness;
+
+public class TableauSpecTest extends MultiThreadedSpecTest {
+
+	public TableauSpecTest() {
+		super("MC", "EWD840", new String[] {"-maxSetSize", "9000000"}, "540765192", "10487806", 0.3d, 0.3d);
+	}
+}
diff --git a/tlatools/test-model/EWD840/EWD840.tla b/tlatools/test-model/EWD840/EWD840.tla
new file mode 100644
index 0000000000000000000000000000000000000000..be06315c2b1a2e48690eb7045554818b1c17a4f9
--- /dev/null
+++ b/tlatools/test-model/EWD840/EWD840.tla
@@ -0,0 +1,98 @@
+------------------------------- MODULE EWD840 -------------------------------
+EXTENDS Naturals
+
+CONSTANT N
+ASSUME NAssumption == N \in Nat \ {0}
+
+VARIABLES active, color, tpos, tcolor
+Nodes == 0 .. N-1
+Color == {"white", "black"}
+
+TypeOK ==
+  /\ active \in [Nodes -> BOOLEAN]
+  /\ color \in [Nodes -> Color]
+  /\ tpos \in Nodes
+  /\ tcolor \in Color
+
+(* Initially the token is at node 0, and it is black. There
+   are no constraints on the status and color of the nodes. *)
+Init ==
+  /\ active \in [Nodes -> BOOLEAN]
+  /\ color \in [Nodes -> Color]
+  /\ tpos = 0
+  /\ tcolor = "black"
+
+InitiateProbe ==
+  /\ tpos = 0
+  /\ tcolor = "black" \/ color[0] = "black"
+  /\ tpos' = N-1
+  /\ tcolor' = "white"
+  /\ color' = [color EXCEPT ![0] = "white"]
+  /\ UNCHANGED <<active>>
+
+PassToken(i) == 
+  /\ tpos = i
+  /\ ~ active[i]
+        \/ color[i] = "black"
+        \/ tcolor = "black"
+  /\ tpos' = i-1
+  /\ tcolor' = IF color[i] = "black" THEN "black" ELSE tcolor
+  /\ color' = [color EXCEPT ![i] = "white"]
+  /\ UNCHANGED <<active>>
+
+SendMsg(i) ==
+  /\ active[i]
+  /\ \E j \in Nodes \ {i} :
+        /\ active' = [active EXCEPT ![j] = TRUE]
+        /\ color' = [color EXCEPT ![i] = IF j>i THEN "black" ELSE @]
+  /\ UNCHANGED <<tpos, tcolor>>
+
+Deactivate(i) ==
+  /\ active[i]
+  /\ active' = [active EXCEPT ![i] = FALSE]
+  /\ UNCHANGED <<color, tpos, tcolor>>
+
+Next ==
+  \/ InitiateProbe
+  \/ \E i \in Nodes \ {0} : PassToken(i)
+  \/ \E i \in Nodes : SendMsg(i) \/ Deactivate(i)
+
+System ==
+  \/ InitiateProbe
+  \/ \E i \in Nodes \ {0} : PassToken(i)
+
+vars == <<active, color, tpos, tcolor>>
+
+Fairness == WF_vars(System)
+
+Spec == Init /\ [][Next]_vars (*/\ Fairness*)
+
+LInv == [][Next]_vars => WF_vars(System)
+
+-----------------------------------------------------------------------------
+
+NeverBlack == \A i \in Nodes : color[i] # "black"
+
+NeverChangeColor == [][ \A i \in Nodes : UNCHANGED color[i] ]_vars
+
+terminationDetected ==
+  /\ tpos = 0 /\ tcolor = "white"
+  /\ color[0] = "white" /\ ~ active[0]
+  /\ color[1] = "white"
+
+TerminationDetection ==
+  terminationDetected => \A i \in Nodes : ~ active[i]
+
+Liveness ==
+  /\ (\A i \in Nodes : ~ active[i]) ~> terminationDetected
+
+AllNodesTerminateIfNoMessages ==
+  <>[][~ \E i \in Nodes : SendMsg(i)]_vars
+  => <>(\A i \in Nodes : ~ active[i])
+
+Inv == 
+  \/ P0:: \A i \in Nodes : tpos < i => ~ active[i]
+  \/ P1:: \E j \in 0 .. tpos : color[j] = "black"
+  \/ P2:: tcolor = "black"
+
+=============================================================================
diff --git a/tlatools/test-model/EWD840/MC.cfg b/tlatools/test-model/EWD840/MC.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..b9114698b9b89d501ee4a9a136f68649f76a3e0a
--- /dev/null
+++ b/tlatools/test-model/EWD840/MC.cfg
@@ -0,0 +1,10 @@
+\* CONSTANT definitions
+CONSTANT
+N <- const_143073460396411000
+\* SPECIFICATION definition
+SPECIFICATION
+spec_143073460397412000
+\* PROPERTY definition
+PROPERTY
+prop_143073460398413000
+\* Generated on Mon May 04 12:16:43 CEST 2015
\ No newline at end of file
diff --git a/tlatools/test-model/EWD840/MC.tla b/tlatools/test-model/EWD840/MC.tla
new file mode 100644
index 0000000000000000000000000000000000000000..532c3aadfef3082d9f6acb4fd394d954d9781418
--- /dev/null
+++ b/tlatools/test-model/EWD840/MC.tla
@@ -0,0 +1,19 @@
+---- MODULE MC ----
+EXTENDS EWD840, TLC
+
+\* CONSTANT definitions @modelParameterConstants:0N
+const_143073460396411000 == 
+10
+----
+
+\* SPECIFICATION definition @modelBehaviorSpec:0
+spec_143073460397412000 ==
+Spec
+----
+\* PROPERTY definition @modelCorrectnessProperties:0
+prop_143073460398413000 ==
+Liveness
+----
+=============================================================================
+\* Modification History
+\* Created Mon May 04 12:16:43 CEST 2015 by markus
diff --git a/tlatools/test-verify/README.txt b/tlatools/test-verify/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9b796debbc8d6eaffebd0008216e94847b918dd2
--- /dev/null
+++ b/tlatools/test-verify/README.txt
@@ -0,0 +1 @@
+This folder contains code to verify TLC with Java Pathfinder (http://babelfish.arc.nasa.gov/trac/jpf/wiki/WikiStart).
\ No newline at end of file
diff --git a/tlatools/test-verify/jpf.properties b/tlatools/test-verify/jpf.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cf1cbb98c00029aaf7c51ca9ca4d46f24a54f1d8
--- /dev/null
+++ b/tlatools/test-verify/jpf.properties
@@ -0,0 +1,437 @@
+# JPF configuration for "jpf-core" component
+
+# path elements can either be relative to the property file location, or
+# use the JPF component name (e.g. "jpf-core") as a variable prefix
+# (e.g. "jpf-core.sourcepath=${jpf-core}/src/examples").
+# If a jpf.properties is to be used within NB, it has to use the variable prefix
+# (prepending the project root is only done during JPF init)
+
+# we use the ';' separator here because it is recognized by NetBeans (as opposed
+# to ',')
+
+# 'config_path' is set automatically by gov.nasa.jpf.Config during JPF init.
+# If used from within an Ant build system, 'jpf-core' has to be set explicitly
+# (ant does ${..} property expansion, but ignores property redefinition, so the
+# following line will be ignored)
+
+jpf-core = ${config_path}
+
+jpf-core.native_classpath=\
+  ${jpf-core}/../lib/jpf.jar;\
+  ${jpf-core}/../lib/jpf-annotations.jar
+
+jpf-core.classpath=\
+  ${jpf-core}/../lib/jpf-classes.jar
+
+#jpf-core.sourcepath=\
+#  ${jpf-core}/src/examples
+
+#jpf-core.test_classpath=\
+#  ${jpf-core}/build/tests
+
+jpf-core.peer_packages = gov.nasa.jpf.vm,<model>,<default>
+
+
+
+# the default jpf-core properties file with keys for which we need mandatory defaults
+
+########################### 0. global part ###############################
+
+# instances that are both search and VM listeners
+#listener = ..
+
+# do we want JPF exceptions to print their stack traces (that's only for
+# debugging)
+jpf.print_exception_stack = true
+
+
+# this is where we can specify additional classpath entries that are
+# not in the system property class.path (e.g. when running JPF from
+# an environment that uses it's own loaders, like Eclipse plugins etc.)
+#jpf.native_classpath = ..
+
+
+########################### 1. Search part ###############################
+search.class = gov.nasa.jpf.search.DFSearch
+
+
+# This flag indicates whether state matching will only be done when a state
+# is revisited at a lower depth. By default this is false. If it is set to
+# true and no error is found in a limited-depth search then it is guaranteed
+# not to have such error below that depth. Note that for traditional
+# depth limited search this does not hold
+search.match_depth = false
+
+# This flag indicates whether JPF should produce more than one error
+# or stop at the first one
+search.multiple_errors = false
+
+# the minimum free memory bounds. If we fall below that threshold, we
+# stop the search
+search.min_free = 1M
+
+# name of the file in which we store error paths. If not set, we don't store
+#search.error_path = error.xml
+
+# the standard properties we want to check for
+search.properties=\
+gov.nasa.jpf.vm.NotDeadlockedProperty,\
+gov.nasa.jpf.vm.NoUncaughtExceptionsProperty
+
+
+# various heuristic parameters
+
+# This number specifies the maximum number of states to keep on the queue
+# during a heuristic search. By default it is set to -1
+search.heuristic.queue_limit = -1
+
+# This flag indicates whether branches with counts less than branch-start
+# are to be ranked according to how many times they have been taken.
+# It is set to true by default. If it is set to false, they are all valued
+# the same
+search.heuristic.branch.count_early = true
+
+# This number determines at what point branches are heuristically valued as worse
+# than non-branching transitions. By default this value is 1.
+branch_start = 1
+
+
+# This number if greater than 0 is returned as the heuristic value for
+# non-branching transitions. By default it is set to -1 in which case the
+# value of branch-start is returned instead
+search.heuristic.branch.no_branch_return = -1
+
+# exclusive search listeners
+# search.listener =
+
+
+############################### 2. VM part ###############################
+
+
+# this is an ordered list of packages from which we try to locate native peers.
+# "<model>" means JPF tries the same package like the model class
+# "<default>" means no package at all
+# (this is going to be extended by jpf.properties files)
+#peer_packages = <model>,<default>
+
+
+vm.class = gov.nasa.jpf.vm.SingleProcessVM
+
+# the ClassLoaderInfo class used for startup
+vm.classloader.class = gov.nasa.jpf.jvm.JVMSystemClassLoaderInfo
+
+# class used to hash/store states (if not set, states are not matched)
+vm.storage.class = gov.nasa.jpf.vm.JenkinsStateSet
+
+# class used to maintain the backtrack stack
+vm.backtracker.class = gov.nasa.jpf.vm.DefaultBacktracker
+
+# serializer to be used by state set (vm.storage.class)
+vm.serializer.class = gov.nasa.jpf.vm.serialize.CFSerializer
+#vm.serializer.class = gov.nasa.jpf.vm.serialize.AdaptiveSerializer
+#vm.serializer.class = gov.nasa.jpf.vm.serialize.FilteringSerializer
+
+# the class that models static fields and classes
+vm.statics.class = gov.nasa.jpf.vm.OVStatics
+
+# the class that models the heap
+#vm.heap.class = gov.nasa.jpf.vm.PSIMHeap
+vm.heap.class = gov.nasa.jpf.vm.OVHeap
+
+# the class representing the list of all threads
+vm.threadlist.class = gov.nasa.jpf.vm.ThreadList
+
+# restorer to be used by backtracker such as DefaultBacktracker UNLESS a
+# serializer that is also a restorer (such as CollapsingSerializer) is used.
+# I.e. this is only read if serializer is not used or it's not a StateRestorer
+vm.restorer.class = .vm.DefaultMementoRestorer
+
+# where do we get the standard libraries from?
+# "<system>" is replaced by the host VM sun.boot.class.path setting
+vm.boot_classpath = <system>
+
+# instruction factory
+jvm.insn_factory.class = gov.nasa.jpf.jvm.bytecode.InstructionFactory
+
+# fields factory
+vm.fields_factory.class = gov.nasa.jpf.vm.DefaultFieldsFactory
+
+# pattern list for assertion enabled/disabled classes
+#vm.enable_assertions = *
+#vm.disable_assertions=
+
+# do we support the Verify.ignorePath() API (to imperatively ignore paths in modeled/instrumented programs)?
+vm.verify.ignore_path = true
+
+
+vm.scheduler.class = gov.nasa.jpf.vm.DelegatingScheduler
+vm.scheduler.sync.class = gov.nasa.jpf.vm.AllRunnablesSyncPolicy
+vm.scheduler.sharedness.class = gov.nasa.jpf.vm.PathSharednessPolicy
+
+# the following properties can be used to set filters for GenericSharednessPolicy instances
+
+# never break on exposure or shared field access from matching methods.
+# NOTE - this is transitive and hence should only include a minimal set of trusted methods
+vm.shared.never_break_methods=\
+      java.util.concurrent.ThreadPoolExecutor.processWorkerExit,\
+      java.util.concurrent.locks.Abstract*Synchronizer.*,\
+      java.util.concurrent.ThreadPoolExecutor.getTask,\
+      java.util.concurrent.atomic.Atomic*.*,\
+      java.util.concurrent.Exchanger.doExchange,\
+      java.util.concurrent.ThreadPoolExecutor.interruptIdleWorkers,\
+      java.util.concurrent.TimeUnit.*
+
+vm.shared.never_break_types=\
+      java.util.concurrent.TimeUnit
+
+# never break on shared access of the following fields. While this is less prone to
+# masking defects than never_break_methods, it should also be used sparingly.
+# NOTE - java.lang.Thread* fields should not be excluded if the SUT explicitly uses 
+# Thread or ThreadGroup objects
+vm.shared.never_break_fields=\
+      java.lang.Thread*.*,\
+      java.lang.System.*,\
+      java.lang.Runtime.*,\
+      java.lang.Boolean.*,\
+      java.lang.String.*,\
+      java.lang.*.TYPE,\
+      java.util.HashMap.EMPTY_TABLE,\
+      java.util.HashSet.PRESENT,\
+      java.util.concurrent.ThreadPoolExecutor*.*,\
+      java.util.concurrent.ThreadPoolExecutor*.*,\
+      java.util.concurrent.TimeUnit.*,\
+      java.util.concurrent.Exchanger.CANCEL,\
+      java.util.concurrent.Exchanger.NULL_ITEM,\
+      java.util.concurrent.Executors$DefaultThreadFactory.*,\
+      sun.misc.VM.*,\
+      sun.misc.SharedSecrets.*,\
+      sun.misc.Unsafe.theUnsafe,\
+      gov.nasa.jpf.util.test.TestJPF.*
+
+
+# do we also break transitions on reference field puts that could make the
+# referenced objects shared
+vm.shared.break_on_exposure = true
+
+# do we try to deduce if a field is supposed to be protected by a lock? In this
+# case, we stop to treat this field as a boundary step, but only if we see the lock
+vm.shared.sync_detection = true
+
+# do we assume final fields to be race-safe (not really true, esp. for
+# instance fields with references leaking from a ctor, but a good starting point)
+vm.shared.skip_finals=true
+
+# ClassLoaders synchronize the loading of a class.
+# Thus, static final fields can never be included in a race condition since only 1 thread is allowed to access the class while it is loading.
+# Defaulted to false to maintain backward compatibility in JPF
+vm.shared.skip_static_finals=false
+
+# When an object's constructor has returned, then the final fields can not be changed.
+# Thus, instance final fields can never be included in a race condition (unless the this reference is leaked from a constructor)
+# Defaulted to false to maintain backward compatibility in JPF
+vm.shared.skip_constructed_finals=false
+
+
+# do we ignore explicitly set Thread.UncaughtHandlers
+vm.ignore_uncaught_handler=false
+
+# do we treat returned Thread.UncaughtHandler.uncaughtException() calls as normal thread termination
+vm.pass_uncaught_handler=true
+
+# do we reclaim unused memory (run garbage collection)
+vm.gc = true
+
+# threshold after which number of allocations to perform a garbage collection
+# (even within the same transition, to avoid lots of short living objects)
+# -1 means never
+vm.max_alloc_gc = -1 
+
+# do we run finalizers on collected objects (only makes sense with garbage collection)
+vm.finalize = false
+
+# this is a preemption boundary specifying the max number of instructions after which we
+# break the current transition if there are other runnable threads
+vm.max_transition_length = 50000
+
+# are thread ids of terminated threads with recycled thread objects reused when creating new
+# threads. This is required for programs that sequentially create many short living threads
+vm.reuse_tid = false
+
+# do we want to halt execution on each throw of an exception that matches
+# one of the given classname wildcard patterns w/o looking for exception handlers?
+# (useful for empty handler blocks, over-permissive catches or generally
+# misused exceptions)
+#vm.halt_on_throw = *
+
+# class that is used to create scheduling relevant choice generators.
+# this will replace the scheduler
+vm.scheduler_factory.class = gov.nasa.jpf.vm.DefaultSchedulerFactory
+
+# print output as it is generated during the search (for all paths)
+vm.tree_output = true
+
+# collect output inside the stored path (to create program trace outout)
+vm.path_output = false
+
+# do we want to store the whole path no matter if we report them
+vm.store_steps=false
+
+# untracked property
+vm.untracked = true
+
+# from where do we initialize the system properties
+#   SELECTED - keys specified as vm.system.properties, values from host
+#   FILE - Java properties file (key=value pairs)
+#   HOST - all system properties from underlying host VM
+vm.sysprop.source = SELECTED
+
+# pathname of property file with system properties
+#vm.sysprop.file =
+
+# list of key names to load from host VM
+#vm.sysprop.keys =
+
+# class we use to model execution time
+vm.time.class = gov.nasa.jpf.vm.SystemTime
+
+# if this is set to true, we throw an exception if we encounter any orphan native peer methods
+vm.no_orphan_methods = false
+
+# if this is set to true, overriden finalize() methods execute upon objects garbage collections
+vm.process_finalizers = false
+
+
+### jvm specifics
+
+# di=o we model nested locks during class init (to detect possible hotspot dealocks during init)
+# (off by default since it can cause state explosion)
+jvm.nested_init=false
+
+# if so, for which classes (default is to exclude system classes)
+jvm.nested_init.exclude=java.*,javax.*,sun.misc.*
+
+
+############################### 3. CG part ###############################
+
+# choice randomization policy in effect:
+#   "NONE" - choice sets are not randomized
+#   "FIXED_SEED" - choice sets are randomized using a fixed seed for each JPF run (reproducible)
+#   "VAR_SEED" - choice sets are randomized using a variable seed for each JPF run
+cg.randomize_choices = NONE
+
+# the standard seed value used for the FIXED_SEED policy
+cg.seed = 42
+
+
+# if this is set, we create choice generators even if there is only a single
+# choice. This is to ensure state storage/matching at all locations where a
+# choice generator *could* be created. The default should be to turn it off though,
+# since this can produce a lot of additional states (esp. with threads)
+cg.break_single_choice = false
+
+
+# default BooleanChoiceGenerator sequence: do we start with 'false'
+cg.boolean.false_first = true
+
+# do we want java.util.Random. nextXX() enumerate choices, or just return a single value?
+# (isn't implemented for all types yet)
+cg.enumerate_random=false
+
+# maximum number of processors returned by Runtime.availableProcessors(). If this is
+# greater than 1, the call represents a ChoiceGenerator
+cg.max_processors=1
+
+# creates a CG upon Thread.start, i.e. breaks the starting transition. Note this is
+# required for data race detection (which depends on detecting access of shared objects)
+cg.threads.break_start=true
+
+# if this option is set we break the transition on Thread.yield()
+cg.threads.break_yield=true
+
+# if this option is set we break the transition on Thread.sleep()
+cg.threads.break_sleep=true
+
+# set if we shold also break on array instructions, e.g. to detect races
+# for array elements. This is off by default because it can cause serious
+# state explosion
+cg.threads.break_arrays=false
+
+# do we support atomic sections. If set to false, Verify.beginAtomic()/endAtomic()
+# will not do anything
+cg.enable_atomic=true
+
+############################### 3. Report Part ###############################
+log.handler.class=gov.nasa.jpf.util.LogHandler
+
+# Windows seem to have a different default
+log.level=warning
+
+report.class=gov.nasa.jpf.report.Reporter
+report.publisher=console
+
+report.console.class=gov.nasa.jpf.report.ConsolePublisher
+
+# this prints out repository information if the 'jpf' topic is set (for debugging)
+#jpf.report.show_repository=true
+
+#property violation reporting is configured separately
+report.console.start=jpf,sut
+
+report.console.transition=
+report.console.constraint=constraint,snapshot
+
+report.console.probe=statistics
+
+report.console.property_violation=error,snapshot
+report.console.show_steps=true
+report.console.show_method=true
+report.console.show_code=false
+
+report.console.finished=result,statistics
+
+#jpf.report.console.show_steps=true
+#jpf.report.console.show_method=true
+#jpf.report.console.show_code=true
+
+report.xml.class=gov.nasa.jpf.report.XMLPublisher
+
+report.html.class=gov.nasa.jpf.report.HTMLPublisher
+report.html.start=jpf,sut,platform,user,dtg,config
+report.html.constraint=constraint
+report.html.property_violation=
+report.html.finished=result,statistics,error,snapshot,output
+
+
+############################### 4. Listener part #############################
+
+# imperative list of listeners
+#listener=
+
+listener.autoload=\
+  gov.nasa.jpf.NonNull,\
+  gov.nasa.jpf.Const
+
+listener.gov.nasa.jpf.NonNull=gov.nasa.jpf.tools.NonNullChecker
+listener.gov.nasa.jpf.Const=gov.nasa.jpf.tools.ConstChecker
+
+
+### PreciseRaceDetector
+
+# we don't check for races in standard libraries
+race.exclude=java.*,javax.*
+
+
+############################### 5. test part #############################
+
+test.report.console.finished=result
+
+###
+### Include both directories created by customBuild.xml as classpath
+### elements. ../class contains the TLC code, ../test-class contains
+### TLC's test code. It's relative to this file jpf.properties to
+### support running the tests from any directory (e.g. via the Eclipse
+### launcher as well as customBuild.xml).
+###
++classpath=${config_path}/../class/;\
+		   ${config_path}/../test-class/
+
diff --git a/tlatools/test-verify/tlc2/tool/queue/StateQueueJPFTest.java b/tlatools/test-verify/tlc2/tool/queue/StateQueueJPFTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea4bc80a8bf128715696af493ac21d00eedd1312
--- /dev/null
+++ b/tlatools/test-verify/tlc2/tool/queue/StateQueueJPFTest.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Microsoft Research. All rights reserved. 
+ *
+ * The MIT License (MIT)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy 
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software. 
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Contributors:
+ *   Markus Alexander Kuppe - initial API and implementation
+ ******************************************************************************/
+
+package tlc2.tool.queue;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import gov.nasa.jpf.util.test.TestJPF;
+import tlc2.tool.TLCState;
+
+public class StateQueueJPFTest extends TestJPF {
+
+	@Test
+	public void test() {
+		if (verifyNoPropertyViolation()) {
+			final StateQueue queue = new DummyStateQueue();
+			final TLCState tlcState = new DummyTLCState();
+			queue.enqueue(tlcState);
+			
+			Thread main = new Thread(new Runnable() {
+				public void run() {
+					queue.suspendAll();
+					// critical section (taking a checkpoint)
+					queue.resumeAll();
+				}
+			}, "Main");
+			main.start();
+			
+			Thread worker = new Thread(new Runnable() {
+				public void run() {
+					for (int i = 0; i < 10; i++) {
+						TLCState state = queue.dequeue();
+						if (state == null) {
+							queue.finishAll();
+							return;
+						}
+						queue.enqueue(tlcState);
+					}
+					queue.finishAll();
+				}
+			}, "Worker");
+			worker.start();
+		}
+	}
+	
+	/*
+	 * Dummy implementation of StateQueue with minimal functionality compared to
+	 * DiskStateQueue or MemStateQueue. After all, we verify the abstract
+	 * StateQueue and not the implementations (which should be done separately).
+	 */
+	private static class DummyStateQueue extends StateQueue {
+
+		private TLCState state;
+
+		void enqueueInner(TLCState state) {
+			this.state = state;
+		}
+
+		TLCState dequeueInner() {
+			return state;
+		}
+
+		public void beginChkpt() throws IOException {
+			// checkpointing not being verified
+		}
+
+		public void commitChkpt() throws IOException {
+			// checkpointing not being verified
+		}
+
+		public void recover() throws IOException {
+			// checkpointing not being verified
+		}
+	}
+}
diff --git a/tlatools/test/tlc2/tool/fp/MSBDiskFPSetTest2.java b/tlatools/test/tlc2/tool/fp/MSBDiskFPSetTest2.java
index 3a8b45495dc17fac58b1dfaf09bffd36db7230ab..e63d7d08339e639a8ac6905d8ec5e82931e0d13f 100644
--- a/tlatools/test/tlc2/tool/fp/MSBDiskFPSetTest2.java
+++ b/tlatools/test/tlc2/tool/fp/MSBDiskFPSetTest2.java
@@ -62,6 +62,24 @@ public class MSBDiskFPSetTest2 extends AbstractHeapBasedDiskFPSetTest {
 		fail();
 	}
 
+	public void testHighFingerprint1() throws RemoteException, IOException {
+		final MSBDiskFPSet msbDiskFPSet = getMSBDiskFPSet();
+		assertFalse(msbDiskFPSet.put(9223368718049406096L));
+		msbDiskFPSet.flusher.flushTable();
+		assertTrue(msbDiskFPSet.put(9223368718049406096L));
+		msbDiskFPSet.flusher.flushTable();
+		assertTrue(msbDiskFPSet.put(9223368718049406096L));
+	}
+
+	public void testHighFingerprint2() throws RemoteException, IOException {
+		final MSBDiskFPSet msbDiskFPSet = getMSBDiskFPSet();
+		assertFalse(msbDiskFPSet.put(9223335424116589377L));
+		msbDiskFPSet.flusher.flushTable();
+		assertTrue(msbDiskFPSet.put(9223335424116589377L));
+		msbDiskFPSet.flusher.flushTable();
+		assertTrue(msbDiskFPSet.put(9223335424116589377L));
+	}
+
 	/*
 	 * Try to get the last element with no elements in the set.
 	 */
@@ -77,6 +95,39 @@ public class MSBDiskFPSetTest2 extends AbstractHeapBasedDiskFPSetTest {
 		}
 		fail();
 	}
+	
+	public void testGetLastWithLowerBound() throws IOException {
+		final MSBDiskFPSet msbDiskFPSet = getMSBDiskFPSet();
+		
+		// Add the largest possible fingerprint into the fpset. It will end up
+		// in the largest bucket. Check that the MSB iterator returns it.
+		final long highFP = 1L << 62;
+		msbDiskFPSet.put(highFP);
+		TLCIterator tlcIterator = new MSBDiskFPSet.TLCIterator(msbDiskFPSet.tbl);
+		assertEquals(highFP, tlcIterator.getLast());
+		
+		// Flush the set to disk (simulating e.g. a checkpoint), a new iterator
+		// won't find the element anymore because it intentionally only searches
+		// for elements that are *not* on disk.
+		msbDiskFPSet.flusher.flushTable();
+		new MSBDiskFPSet.TLCIterator(msbDiskFPSet.tbl);
+		try {
+			tlcIterator.getLast();
+		} catch (NoSuchElementException e) {
+			// This exception is expected.
+			
+			// Now add the smallest possible element into the set. It will end
+			// up in the smallest bucket.
+			final long lowFP = 1;
+			msbDiskFPSet.put(lowFP);
+			// check that the iterator finds lower bound as the last element.
+			tlcIterator = new MSBDiskFPSet.TLCIterator(msbDiskFPSet.tbl);
+			final long lowerBound = highFP - 1L;
+			assertEquals(lowerBound, tlcIterator.getLast(lowerBound));
+			return;
+		}
+		fail();
+	}
 
 	private MSBDiskFPSet getMSBDiskFPSet() throws RemoteException, IOException {
 		// Create an MSBDiskFPSet usable in this unit test with memory allocated
diff --git a/tlatools/test/tlc2/tool/fp/iterator/TLCIterator2Test.java b/tlatools/test/tlc2/tool/fp/iterator/TLCIterator2Test.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ac9f4ed03130d4cd1b039e0255262fbaaf62d73
--- /dev/null
+++ b/tlatools/test/tlc2/tool/fp/iterator/TLCIterator2Test.java
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
+
+package tlc2.tool.fp.iterator;
+
+public class TLCIterator2Test extends TLCIteratorTest {
+
+	/* (non-Javadoc)
+	 * @see tlc2.tool.fp.iterator.TLCIteratorTest#getBuffer()
+	 */
+	@Override
+	protected long[][] getBuffer() {
+		final long[][] buff = new long[8][];
+		buff[0] = getArray(8, 1, 8);
+		buff[1] = getArray(8, 9, 6);
+		buff[2] = null;
+		buff[3] = null;
+		
+		buff[4] = getArray(8, 15, 7); // Bucket with last element
+		buff[5] = null;
+		
+		// Simulate that this bucket is filled with fingerprints who have all
+		// been flushed to disk.
+		buff[6] = new long[4];
+		buff[6][0] = 22L | 0x8000000000000000L;
+		buff[6][1] = 0L;
+		buff[6][2] = 0L;
+		buff[6][3] = 0L;
+		
+		buff[7] = null;
+		return buff;
+	}
+}
diff --git a/tlatools/test/tlc2/tool/fp/iterator/TLCIteratorTest.java b/tlatools/test/tlc2/tool/fp/iterator/TLCIteratorTest.java
index b15ac8788631cfe688dd4b14041b13412409e4d7..07f347f360dc46568a3a506f3abbbf935dfa7149 100644
--- a/tlatools/test/tlc2/tool/fp/iterator/TLCIteratorTest.java
+++ b/tlatools/test/tlc2/tool/fp/iterator/TLCIteratorTest.java
@@ -94,4 +94,16 @@ public class TLCIteratorTest extends TestCase {
 	public void testGetLast() {
 		assertEquals(getLast(), itr.getLast());
 	}
+
+	public void testGetLastLowBound() {
+		assertEquals(getLast() + 1, itr.getLast(getLast() + 1));
+	}
+	
+	/*
+	 * Use a smaller lower bound element than last in the buffer.
+	 */
+	public void testGetLastLowerBoundNoHit() {
+		assertEquals(getLast(), itr.getLast(20));
+	}
+
 }
diff --git a/tlatools/test/tlc2/tool/liveness/ModelCheckerTestCase.java b/tlatools/test/tlc2/tool/liveness/ModelCheckerTestCase.java
index f2c8ba8b1a14afdb4872dc32109da340da675dc9..ba50d0b6e2c57183fc956e6939d662b7abb8edeb 100644
--- a/tlatools/test/tlc2/tool/liveness/ModelCheckerTestCase.java
+++ b/tlatools/test/tlc2/tool/liveness/ModelCheckerTestCase.java
@@ -23,7 +23,6 @@
  * Contributors:
  *   Markus Alexander Kuppe - initial API and implementation
  ******************************************************************************/
-
 package tlc2.tool.liveness;
 
 import java.io.File;
@@ -72,15 +71,27 @@ public abstract class ModelCheckerTestCase extends TestCase {
 			final TLC tlc = new TLC();
 			// * We want *no* deadlock checking to find the violation of the
 			// temporal formula
-			// * We use a single worker to simplify debugging by taking out
-			// threading
+			// * We use (unless overridden) a single worker to simplify
+			// debugging by taking out threading
 			// * MC is the name of the TLA+ specification to be checked (the file
 			// is placed in TEST_MODEL
-			final List<String> args = new ArrayList<String>(4);
+			final List<String> args = new ArrayList<String>(6);
+			
+			// *Don't* check for deadlocks. All tests are interested in liveness
+			// checks which are shielded away by deadlock checking. TLC finds a
+			// deadlock (if it exists) before it finds most liveness violations.
 			args.add("-deadlock");
+			
 			args.add("-workers");
-			args.add(getNumberOfThreads());
+			args.add(Integer.toString(getNumberOfThreads()));
+			
+			// Never create checkpoints. They distort performance tests and are
+			// of no use anyway.
+			args.add("-checkpoint");
+			args.add("0");
+
 			args.addAll(Arrays.asList(extraArguments));
+			
 			args.add(spec);
 			tlc.handleParameters(args.toArray(new String[args.size()]));
 			
@@ -88,11 +99,11 @@ public abstract class ModelCheckerTestCase extends TestCase {
 			tlc.process();
 			
 		} catch (Exception e) {
-			fail();
+			fail(e.getMessage());
 		}
 	}
 
-	protected String getNumberOfThreads() {
-		return "1";
+	protected int getNumberOfThreads() {
+		return 1;
 	}
 }