Index: tests/concurrent/.expect/spinaphore.txt
===================================================================
--- tests/concurrent/.expect/spinaphore.txt	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
+++ tests/concurrent/.expect/spinaphore.txt	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
@@ -0,0 +1,3 @@
+Starting
+Done!
+Match!
Index: tests/concurrent/spinaphore.cfa
===================================================================
--- tests/concurrent/spinaphore.cfa	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
+++ tests/concurrent/spinaphore.cfa	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
@@ -0,0 +1,97 @@
+#include <fstream.hfa>
+#include <locks.hfa>
+#include <thread.hfa>
+
+enum { num_blockers = 17, num_unblockers = 13 };
+
+void thrash() {
+	unsigned t[100];
+	for(i; 100) {
+		t[i] = 0xDEADBEEF;
+	}
+}
+
+Semaphore0nary sem;
+
+const unsigned int num_blocks = 1625;
+
+thread Blocker {
+	size_t sum;
+};
+void main(Blocker & this);
+
+Blocker * from_thread($thread * t) {
+	Blocker & nullb = *(Blocker*)0p;
+	$thread & nullt = (thread&)nullb;
+	uintptr_t offset  = (uintptr_t)&nullt;
+	uintptr_t address = ((uintptr_t)t) - offset;
+	return (Blocker*)address;
+}
+
+void main(Blocker & this) {
+	$thread * me = active_thread();
+	Blocker * me1 = &this;
+	Blocker * me2 = from_thread(me);
+	if( me1 != me2 ) sout | "Bad casting!" | me1 | "vs" | me2;
+	this.sum = 0;
+	for(num_blocks) {
+		// sout | "b P" | me;
+		P(sem);
+		if(((thread&)this).seqable.next != 0p) sout | "Link not invalidated";
+		// sout | "a P" | me;
+	}
+}
+
+const unsigned int num_unblocks = 2125;
+
+thread Unblocker {
+	size_t sum;
+};
+
+void main(Unblocker & this) {
+	this.sum = 0;
+	unsigned me = (unsigned)&this;
+	for(num_unblocks) {
+		$thread * t = V(sem, false);
+		Blocker * b = from_thread(t);
+		b->sum += me;
+		this.sum += (unsigned)b;
+		unpark(t);
+		// sout | "a V" | t;
+		yield(random(10));
+	}
+}
+
+int main() {
+	size_t usum = 0;
+	size_t bsum = 0;
+
+	if((num_unblocks * num_unblockers) != (num_blocks * num_blockers)) sout | "Mismatched Operations: " | (num_unblocks * num_unblockers) | "vs" | (num_blocks * num_blockers);
+
+	sout | "Starting";
+	{
+		Blocker   blockers  [num_blockers  ];
+		Unblocker unblockers[num_unblockers];
+
+		for(i;num_blockers) {
+			for(num_blocks)
+				usum += (unsigned)&blockers[i];
+		}
+
+		for(i;num_unblockers) {
+			for(num_unblocks)
+				bsum += (unsigned)&unblockers[i];
+		}
+
+		for(i;num_blockers) {
+			bsum -= join(blockers[i]).sum;
+		}
+
+		for(i;num_unblockers) {
+			usum -= join(unblockers[i]).sum;
+		}
+	}
+	sout | "Done!";
+	if(bsum == 0 && usum == 0) sout | "Match!";
+	else sout | "No Match!" | usum | "/" | bsum;
+}
Index: tests/unified_locking/.expect/mcs.txt
===================================================================
--- tests/unified_locking/.expect/mcs.txt	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
+++ tests/unified_locking/.expect/mcs.txt	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
@@ -0,0 +1,3 @@
+Starting
+Done!
+Match!
Index: tests/unified_locking/mcs.cfa
===================================================================
--- tests/unified_locking/mcs.cfa	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
+++ tests/unified_locking/mcs.cfa	(revision c51124b6a42d9c4dc5ac13c1d61fef7ba7ab64c5)
@@ -0,0 +1,66 @@
+#include <fstream.hfa>
+#include <locks.hfa>
+#include <thread.hfa>
+
+const unsigned int num_times = 50000;
+
+struct MutexObj {
+	mcs_lock l;
+	$thread * id;
+	size_t sum;
+};
+
+MutexObj mo;
+
+void trash() {
+	unsigned t[100];
+	for(i; 100) {
+		t[i] = 0xDEADBEEF;
+	}
+}
+
+unsigned cs() {
+	$thread * me = active_thread();
+	unsigned value = (unsigned)me;
+	mcs_node n;
+	lock(mo.l, n);
+	{
+		size_t tsum = mo.sum;
+		mo.id = me;
+		yield(random(5));
+		if(mo.id != me) sout | "Intruder!";
+		mo.sum = tsum + value;
+	}
+	unlock(mo.l, n);
+	return value;
+}
+
+thread LockCheck {
+	size_t sum;
+};
+
+void main(LockCheck & this) {
+	this.sum = 0;
+	for(num_times) {
+		trash();
+		this.sum += cs();
+		trash();
+		yield(random(10));
+	}
+}
+
+int main() {
+	size_t sum = -32;
+	mo.sum = -32;
+	processor p[2];
+	sout | "Starting";
+	{
+		LockCheck checkers[13];
+		for(i;13) {
+			sum += join(checkers[i]).sum;
+		}
+	}
+	sout | "Done!";
+	if(sum == mo.sum) sout | "Match!";
+	else sout | "No Match!" | sum | "vs" | mo.sum;
+}
