Index: doc/theses/andrew_beach_MMath/future.tex
===================================================================
--- doc/theses/andrew_beach_MMath/future.tex	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ doc/theses/andrew_beach_MMath/future.tex	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -83,4 +83,29 @@
 patterns to find the handler.
 
+\section{Checked Exceptions}
+Checked exceptions make exceptions part of a function's type by adding the
+exception signature. An exception signature must declare all checked
+exceptions that could propogate from the function (either because they were
+raised inside the function or came from a sub-function). This improves safety
+by making sure every checked exception is either handled or consciously
+passed on.
+
+However checked exceptions were never seriously considered for this project
+for two reasons. The first is due to time constraints, even copying an
+existing checked exception system would be pushing the remaining time and
+trying to address the second problem would take even longer. The second
+problem is that checked exceptions have some real usability trade-offs in
+exchange for the increased safety.
+
+These trade-offs are most problematic when trying to pass exceptions through
+higher-order functions from the functions the user passed into the
+higher-order function. There are no well known solutions to this problem
+that were statifactory for \CFA (which carries some of C's flexability
+over safety design) so one would have to be researched and developed.
+
+Follow-up work might add checked exceptions to \CFA, possibly using
+polymorphic exception signatures, a form of tunneling\cite{Zhang19} or
+checked and unchecked raises.
+
 \section{Zero-Cost Try}
 \CFA does not have zero-cost try-statements because the compiler generates C
Index: libcfa/src/bits/weakso_locks.cfa
===================================================================
--- libcfa/src/bits/weakso_locks.cfa	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ libcfa/src/bits/weakso_locks.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -18,13 +18,12 @@
 #include "bits/weakso_locks.hfa"
 
-void  ?{}( blocking_lock & this, bool multi_acquisition, bool strict_owner ) {}
-void ^?{}( blocking_lock & this ) {}
+void  ?{}( blocking_lock &, bool, bool ) {}
+void ^?{}( blocking_lock & ) {}
 
-void lock( blocking_lock & this ) {}
-bool try_lock( blocking_lock & this ) { return false; }
-void unlock( blocking_lock & this ) {}
-void on_notify( blocking_lock & this, struct $thread * t ) {}
-void on_wait( blocking_lock & this ) {}
-size_t wait_count( blocking_lock & this ) { return 0; }
-void set_recursion_count( blocking_lock & this, size_t recursion ) {}
-size_t get_recursion_count( blocking_lock & this ) { return 0; }
+void lock( blocking_lock & ) {}
+bool try_lock( blocking_lock & ) { return false; }
+void unlock( blocking_lock & ) {}
+void on_notify( blocking_lock &, struct $thread * ) {}
+size_t on_wait( blocking_lock & ) {}
+void on_wakeup( blocking_lock &, size_t ) {}
+size_t wait_count( blocking_lock & ) { return 0; }
Index: libcfa/src/bits/weakso_locks.hfa
===================================================================
--- libcfa/src/bits/weakso_locks.hfa	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ libcfa/src/bits/weakso_locks.hfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -56,8 +56,7 @@
 void unlock( blocking_lock & this ) OPTIONAL_THREAD;
 void on_notify( blocking_lock & this, struct $thread * t ) OPTIONAL_THREAD;
-void on_wait( blocking_lock & this ) OPTIONAL_THREAD;
+size_t on_wait( blocking_lock & this ) OPTIONAL_THREAD;
+void on_wakeup( blocking_lock & this, size_t ) OPTIONAL_THREAD;
 size_t wait_count( blocking_lock & this ) OPTIONAL_THREAD;
-void set_recursion_count( blocking_lock & this, size_t recursion ) OPTIONAL_THREAD;
-size_t get_recursion_count( blocking_lock & this ) OPTIONAL_THREAD;
 
 //----------
@@ -72,6 +71,5 @@
 static inline bool   try_lock ( multiple_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
 static inline void   unlock   ( multiple_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
-static inline void   on_wait  ( multiple_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); }
+static inline size_t on_wait  ( multiple_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
+static inline void   on_wakeup( multiple_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
 static inline void   on_notify( multiple_acquisition_lock & this, struct $thread * t ){ on_notify( (blocking_lock &)this, t ); }
-static inline void   set_recursion_count( multiple_acquisition_lock & this, size_t recursion ){ set_recursion_count( (blocking_lock &)this, recursion ); }
-static inline size_t get_recursion_count( multiple_acquisition_lock & this ){ return get_recursion_count( (blocking_lock &)this ); }
Index: libcfa/src/concurrency/locks.cfa
===================================================================
--- libcfa/src/concurrency/locks.cfa	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ libcfa/src/concurrency/locks.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -134,5 +134,6 @@
 	lock( lock __cfaabi_dbg_ctx2 );
 	/* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
-	/* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
+	/* paranoid */ verifyf( owner == active_thread() || !strict_owner , "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
+	/* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to release owner lock %p which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count );
 
 	// if recursion count is zero release lock and set new owner if one is waiting
@@ -146,12 +147,4 @@
 size_t wait_count( blocking_lock & this ) with( this ) {
 	return wait_count;
-}
-
-void set_recursion_count( blocking_lock & this, size_t recursion ) with( this ) {
-	recursion_count = recursion;
-}
-
-size_t get_recursion_count( blocking_lock & this ) with( this ) {
-	return recursion_count;
 }
 
@@ -173,11 +166,18 @@
 }
 
-void on_wait( blocking_lock & this ) with( this ) {
+size_t on_wait( blocking_lock & this ) with( this ) {
 	lock( lock __cfaabi_dbg_ctx2 );
 	/* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
 	/* paranoid */ verifyf( owner == active_thread() || !strict_owner, "Thread %p other than the owner %p attempted to release owner lock %p", owner, active_thread(), &this );
 
+	size_t ret = recursion_count;
+
 	pop_and_set_new_owner( this );
 	unlock( lock );
+	return ret;
+}
+
+void on_wakeup( blocking_lock & this, size_t recursion ) with( this ) {
+	recursion_count = recursion;
 }
 
@@ -274,5 +274,10 @@
 	}
 
-	bool empty( condition_variable(L) & this ) with(this) { return empty(blocked_threads); }
+	bool empty( condition_variable(L) & this ) with(this) {
+		lock( lock __cfaabi_dbg_ctx2 );
+		bool ret = empty(blocked_threads);
+		unlock( lock );
+		return ret;
+	}
 
 	int counter( condition_variable(L) & this ) with(this) { return count; }
@@ -285,6 +290,5 @@
 		if (i->lock) {
 			// if lock was passed get recursion count to reset to after waking thread
-			recursion_count = get_recursion_count(*i->lock);
-			on_wait( *i->lock );
+			recursion_count = on_wait( *i->lock );
 		}
 		return recursion_count;
@@ -301,5 +305,5 @@
 
 		// resets recursion count here after waking
-		if (i.lock) set_recursion_count(*i.lock, recursion_count);
+		if (i.lock) on_wakeup(*i.lock, recursion_count);
 	}
 
@@ -323,5 +327,5 @@
 
 		// resets recursion count here after waking
-		if (info.lock) set_recursion_count(*info.lock, recursion_count);
+		if (info.lock) on_wakeup(*info.lock, recursion_count);
 	}
 
@@ -373,5 +377,5 @@
 }
 
-bool V(semaphore & this) with( this ) {
+$thread * V (semaphore & this, const bool doUnpark ) with( this ) {
 	$thread * thrd = 0p;
 	lock( lock __cfaabi_dbg_ctx2 );
@@ -385,6 +389,11 @@
 
 	// make new owner
-	unpark( thrd );
-
+	if( doUnpark ) unpark( thrd );
+
+	return thrd;
+}
+
+bool V(semaphore & this) with( this ) {
+	$thread * thrd = V(this, true);
 	return thrd != 0p;
 }
Index: libcfa/src/concurrency/locks.hfa
===================================================================
--- libcfa/src/concurrency/locks.hfa	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ libcfa/src/concurrency/locks.hfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -39,5 +39,4 @@
 };
 
-static inline bool P(Semaphore0nary & this, $thread * thrd) __attribute__((artificial));
 static inline bool P(Semaphore0nary & this, $thread * thrd) {
 	/* paranoid */ verify(!(thrd->seqable.next));
@@ -48,5 +47,4 @@
 }
 
-static inline bool P(Semaphore0nary & this) __attribute__((artificial));
 static inline bool P(Semaphore0nary & this) {
     $thread * thrd = active_thread();
@@ -56,6 +54,5 @@
 }
 
-static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) __attribute__((artificial));
-static inline $thread * V(Semaphore0nary & this, const bool doUnpark = true) {
+static inline $thread * V(Semaphore0nary & this, bool doUnpark = true) {
 	$thread * next;
 	lock(this.lock __cfaabi_dbg_ctx2);
@@ -82,5 +79,8 @@
 
 	// returns true if no blocking needed
-	bool P(BinaryBenaphore & this) { return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0; }
+	bool P(BinaryBenaphore & this) {
+		return __atomic_fetch_sub(&this.counter, 1, __ATOMIC_SEQ_CST) > 0;
+	}
+
 	bool tryP(BinaryBenaphore & this) {
 		ssize_t c = this.counter;
@@ -115,11 +115,10 @@
 static inline void ?{}(ThreadBenaphore & this, one_t ) { (this.ben){ 1 }; }
 
-static inline bool P(ThreadBenaphore & this)              { return /* P(this.ben) ? false : */ P(this.sem); }
-static inline bool P(ThreadBenaphore & this, $thread * t) { return /* P(this.ben) ? false : */ P(this.sem, t ); }
+static inline bool P(ThreadBenaphore & this)              { return P(this.ben) ? false : P(this.sem); }
 static inline bool tryP(ThreadBenaphore & this)           { return tryP(this.ben); }
 static inline bool P(ThreadBenaphore & this, bool wait)   { return wait ? P(this) : tryP(this); }
 
-static inline $thread * V(ThreadBenaphore & this, const bool doUnpark = true) {
-	// if (V(this.ben)) return 0p;
+static inline $thread * V(ThreadBenaphore & this, bool doUnpark = true) {
+	if (V(this.ben)) return 0p;
 	return V(this.sem, doUnpark);
 }
@@ -138,4 +137,5 @@
 bool   V (semaphore & this);
 bool   V (semaphore & this, unsigned count);
+$thread * V (semaphore & this, bool );
 
 //----------
@@ -146,11 +146,10 @@
 static inline void  ?{}( single_acquisition_lock & this ) {((blocking_lock &)this){ false, false };}
 static inline void ^?{}( single_acquisition_lock & this ) {}
-static inline void   lock      ( single_acquisition_lock & this ) { lock    ( (blocking_lock &)this ); }
-static inline bool   try_lock  ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
-static inline void   unlock    ( single_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
-static inline void   on_wait   ( single_acquisition_lock & this ) { on_wait ( (blocking_lock &)this ); }
-static inline void   on_notify ( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
-static inline void   set_recursion_count( single_acquisition_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
-static inline size_t get_recursion_count( single_acquisition_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
+static inline void   lock     ( single_acquisition_lock & this ) { lock    ( (blocking_lock &)this ); }
+static inline bool   try_lock ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
+static inline void   unlock   ( single_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
+static inline size_t on_wait  ( single_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
+static inline void   on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
+static inline void   on_notify( single_acquisition_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
 
 //----------
@@ -164,8 +163,7 @@
 static inline bool   try_lock ( owner_lock & this ) { return try_lock( (blocking_lock &)this ); }
 static inline void   unlock   ( owner_lock & this ) { unlock  ( (blocking_lock &)this ); }
-static inline void   on_wait  ( owner_lock & this ) { on_wait ( (blocking_lock &)this ); }
+static inline size_t on_wait  ( owner_lock & this ) { return on_wait ( (blocking_lock &)this ); }
+static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
 static inline void   on_notify( owner_lock & this, struct $thread * t ) { on_notify( (blocking_lock &)this, t ); }
-static inline void   set_recursion_count( owner_lock & this, size_t recursion ) { set_recursion_count( (blocking_lock &)this, recursion ); }
-static inline size_t get_recursion_count( owner_lock & this ) { return get_recursion_count( (blocking_lock &)this ); }
 
 struct fast_lock {
@@ -179,13 +177,5 @@
 }
 
-static inline void $lock(fast_lock & this, $thread * thrd) {
-	/* paranoid */verify(thrd != this.owner);
-
-	for (;;) {
-		if ($try_lock(this, thrd)) return;
-		P(this.sem, thrd);
-	}
-}
-
+static inline void lock( fast_lock & this ) __attribute__((artificial));
 static inline void lock( fast_lock & this ) {
 	$thread * thrd = active_thread();
@@ -198,5 +188,6 @@
 }
 
-static inline void try_lock ( fast_lock & this ) {
+static inline bool try_lock( fast_lock & this ) __attribute__((artificial));
+static inline bool try_lock ( fast_lock & this ) {
 	$thread * thrd = active_thread();
 	/* paranoid */ verify(thrd != this.owner);
@@ -204,27 +195,20 @@
 }
 
-static inline void unlock( fast_lock & this ) {
+static inline $thread * unlock( fast_lock & this ) __attribute__((artificial));
+static inline $thread * unlock( fast_lock & this ) {
 	$thread * thrd = active_thread();
 	/* paranoid */ verify(thrd == this.owner);
-	$thread * next = V(this.sem, false); // implicit fence
-	// open 'owner' only after fence
+
+	// open 'owner' before unlocking anyone
+	// so new and unlocked threads don't park incorrectly.
+	// This may require additional fencing on ARM.
 	this.owner = 0p;
 
-	// Unpark the next person (can be 0p, unpark handles it)
-	unpark(next);
-}
-
-static inline void on_wait( fast_lock & this ) {
-	unlock(this);
-	#warning this is broken
-}
-
-static inline void on_notify( fast_lock & this, struct $thread * t ) {
-	$lock(this, t);
-	#warning this is broken
-}
-
-static inline void   set_recursion_count( fast_lock & this, size_t recursion ) {}
-static inline size_t get_recursion_count( fast_lock & this ) { return 0; }
+	return V(this.sem);
+}
+
+static inline size_t on_wait( fast_lock & this ) { unlock(this); return 0; }
+static inline void on_wakeup( fast_lock & this, size_t ) { lock(this); }
+static inline void on_notify( fast_lock &, struct $thread * t ) { unpark(t); }
 
 struct mcs_node {
@@ -260,11 +244,8 @@
 
 	// For synchronization locks to use when releasing
-	void on_wait( L & );
-
-	// to get recursion count for cond lock to reset after waking
-	size_t get_recursion_count( L & );
+	size_t on_wait( L & );
 
 	// to set recursion count after getting signalled;
-	void set_recursion_count( L &, size_t recursion );
+	void on_wakeup( L &, size_t recursion );
 };
 
Index: tests/concurrent/.expect/semaphore.txt
===================================================================
--- tests/concurrent/.expect/semaphore.txt	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
+++ tests/concurrent/.expect/semaphore.txt	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -0,0 +1,3 @@
+Starting
+Done!
+Match!
Index: tests/concurrent/semaphore.cfa
===================================================================
--- tests/concurrent/semaphore.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
+++ tests/concurrent/semaphore.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -0,0 +1,77 @@
+#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;
+	}
+}
+
+ThreadBenaphore ben;
+
+// const unsigned int num_blocks = 25000;
+const unsigned int num_blocks = 5;
+
+thread Blocker {
+	size_t sum;
+};
+
+void main(Blocker & this) {
+	$thread * me = active_thread();
+	this.sum = 0;
+	for(num_blocks) {
+		this.sum += (unsigned)me;
+		thrash();
+		P(ben);
+		if(((thread&)this).seqable.next != 0p) sout | acquire |"Link not invalidated";
+		thrash();
+	}
+}
+
+thread Unblocker {
+	size_t sum;
+};
+
+void main(Unblocker & this) {
+	this.sum = 0;
+	LOOP: for() {
+		waitfor( ^?{} : this) {
+			break LOOP;
+		}
+		or else {}
+
+		$thread * t = V(ben, false);
+		if(t) {
+			this.sum += (unsigned)t;
+			unpark(t);
+		}
+		yield(random(10));
+	}
+}
+
+int main() {
+	size_t usum = 0;
+	size_t bsum = 0;
+
+	sout | "Starting";
+	{
+		Blocker   blockers  [num_blockers  ];
+		Unblocker unblockers[num_unblockers];
+
+		for(i;num_blockers) {
+			bsum += join(blockers[i]).sum;
+		}
+
+		sout | "Done!";
+
+		for(i;num_unblockers) {
+			usum += join(unblockers[i]).sum;
+		}
+	}
+	if(bsum == usum) sout | "Match!";
+	else sout | "No Match!" | usum | "!=" | bsum;
+}
Index: tests/concurrent/spinaphore.cfa
===================================================================
--- tests/concurrent/spinaphore.cfa	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ tests/concurrent/spinaphore.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -36,8 +36,6 @@
 	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;
 	}
 }
@@ -58,5 +56,4 @@
 		this.sum += (unsigned)b;
 		unpark(t);
-		// sout | "a V" | t;
 		yield(random(10));
 	}
Index: tests/unified_locking/.expect/fast.txt
===================================================================
--- tests/unified_locking/.expect/fast.txt	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
+++ tests/unified_locking/.expect/fast.txt	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -0,0 +1,3 @@
+Starting
+Done!
+Match!
Index: tests/unified_locking/.expect/locks.txt
===================================================================
--- tests/unified_locking/.expect/locks.txt	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ tests/unified_locking/.expect/locks.txt	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -11,10 +11,14 @@
 Start Test 6: owner lock and condition variable 3 wait/notify all
 Done Test 6
-Start Test 7: multi acquisiton lock and condition variable multiple acquire and wait/notify
+Start Test 7: fast lock and condition variable single wait/notify
 Done Test 7
-Start Test 8: owner lock and condition variable multiple acquire and wait/notify
+Start Test 8: fast lock and condition variable 3 wait/notify all
 Done Test 8
-Start Test 9: no lock condition variable wait/notify
+Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify
 Done Test 9
-Start Test 10: locked condition variable wait/notify with front()
+Start Test 10: owner lock and condition variable multiple acquire and wait/notify
 Done Test 10
+Start Test 11: no lock condition variable wait/notify
+Done Test 11
+Start Test 12: locked condition variable wait/notify with front()
+Done Test 12
Index: tests/unified_locking/fast.cfa
===================================================================
--- tests/unified_locking/fast.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
+++ tests/unified_locking/fast.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -0,0 +1,65 @@
+#include <fstream.hfa>
+#include <locks.hfa>
+#include <thread.hfa>
+
+const unsigned int num_times = 50;
+
+struct MutexObj {
+	fast_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;
+	lock(mo.l);
+	{
+		size_t tsum = mo.sum;
+		mo.id = me;
+		yield(random(5));
+		if(mo.id != me) sout | "Intruder!";
+		mo.sum = tsum + value;
+	}
+	unlock(mo.l);
+	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;
+}
Index: tests/unified_locking/locks.cfa
===================================================================
--- tests/unified_locking/locks.cfa	(revision 3bd24649fd7d0a7b3339bba8baeb8076292c6b06)
+++ tests/unified_locking/locks.cfa	(revision b580bcc79ab67014709f2d38fb67132e54d6e92f)
@@ -15,4 +15,7 @@
 condition_variable( owner_lock ) c_o;
 
+fast_lock f;
+condition_variable( fast_lock ) c_f;
+
 thread T_C_M_WS1 {};
 
@@ -68,4 +71,32 @@
 		}
 		unlock(s);
+	}
+}
+
+thread T_C_F_WS1 {};
+
+void main( T_C_F_WS1 & this ) {
+	for (unsigned int i = 0; i < num_times; i++) {
+		lock(f);
+		if(empty(c_f) && i != num_times - 1) {
+			wait(c_f,f);
+		}else{
+			notify_one(c_f);
+		}
+		unlock(f);
+	}
+}
+
+thread T_C_F_WB1 {};
+
+void main( T_C_F_WB1 & this ) {
+	for (unsigned int i = 0; i < num_times; i++) {
+		lock(f);
+		if(counter(c_f) == 3 || i == num_times - 1) {
+			notify_all(c_f);
+		}else{
+			wait(c_f,f);
+		}
+		unlock(f);
 	}
 }
@@ -255,28 +286,40 @@
 	printf("Done Test 6\n");
 
-	printf("Start Test 7: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
+	printf("Start Test 7: fast lock and condition variable single wait/notify\n");
+	{
+		T_C_F_WS1 t1[2];
+	}
+	printf("Done Test 7\n");
+
+	printf("Start Test 8: fast lock and condition variable 3 wait/notify all\n");
+	{
+		T_C_F_WB1 t1[4];
+	}
+	printf("Done Test 8\n");
+
+	printf("Start Test 9: multi acquisiton lock and condition variable multiple acquire and wait/notify\n");
 	{
 		T_C_M_WS2 t1[2];
 	}
-	printf("Done Test 7\n");
-
-	printf("Start Test 8: owner lock and condition variable multiple acquire and wait/notify\n");
+	printf("Done Test 9\n");
+
+	printf("Start Test 10: owner lock and condition variable multiple acquire and wait/notify\n");
 	{
 		T_C_O_WS2 t1[2];
 	}
-	printf("Done Test 8\n");
-
-	printf("Start Test 9: no lock condition variable wait/notify\n");
+	printf("Done Test 10\n");
+
+	printf("Start Test 11: no lock condition variable wait/notify\n");
 	{
 		T_C_NLW t1;
 		T_C_NLS t2;
 	}
-	printf("Done Test 9\n");
-
-	printf("Start Test 10: locked condition variable wait/notify with front()\n");
+	printf("Done Test 11\n");
+
+	printf("Start Test 12: locked condition variable wait/notify with front()\n");
 	{
 		T_C_S_WNF t1[2];
 	}
-	printf("Done Test 10\n");
+	printf("Done Test 12\n");
 
 	// removed to limit test duration. Full test is in long run tests
