Index: libcfa/src/concurrency/locks.hfa
===================================================================
--- libcfa/src/concurrency/locks.hfa	(revision bd72c28427f616ee95dc08f6845fe25cfead577d)
+++ libcfa/src/concurrency/locks.hfa	(revision 63d5ac5fb11e5284280a042ca1b3761700ff219b)
@@ -30,4 +30,6 @@
 #include "time.hfa"
 
+#include "select.hfa"
+
 #include <fstream.hfa>
 
@@ -70,4 +72,7 @@
 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 ); }
+static inline bool   register_select( single_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
+static inline bool   unregister_select( single_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); }
+static inline bool   on_selected( single_acquisition_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); }
 
 //----------
@@ -84,4 +89,7 @@
 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 bool   register_select( owner_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
+static inline bool   unregister_select( owner_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); }
+static inline bool   on_selected( owner_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); }
 
 //-----------------------------------------------------------------------------
@@ -180,5 +188,5 @@
 
 // if this is called recursively IT WILL DEADLOCK!!!!!
-static inline void lock(futex_mutex & this) with(this) {
+static inline void lock( futex_mutex & this ) with(this) {
 	int state;
 
@@ -190,7 +198,4 @@
 		for (int i = 0; i < spin; i++) Pause();
 	}
-
-	// // no contention try to acquire
-	// if (internal_try_lock(this, state)) return;
 	
 	// if not in contended state, set to be in contended state
@@ -213,5 +218,5 @@
 
 static inline void on_notify( futex_mutex & f, thread$ * t){ unpark(t); }
-static inline size_t on_wait( futex_mutex & f ) {unlock(f); return 0;}
+static inline size_t on_wait( futex_mutex & f ) { unlock(f); park(); return 0; }
 
 // to set recursion count after getting signalled;
@@ -244,5 +249,5 @@
 
 // if this is called recursively IT WILL DEADLOCK!!!!!
-static inline void lock(go_mutex & this) with(this) {
+static inline void lock( go_mutex & this ) with( this ) {
 	int state, init_state;
 
@@ -255,5 +260,5 @@
             while( !val ) { // lock unlocked
                 state = 0;
-                if (internal_try_lock(this, state, init_state)) return;
+                if ( internal_try_lock( this, state, init_state ) ) return;
             }
             for (int i = 0; i < 30; i++) Pause();
@@ -262,13 +267,13 @@
         while( !val ) { // lock unlocked
             state = 0;
-            if (internal_try_lock(this, state, init_state)) return;
+            if ( internal_try_lock( this, state, init_state ) ) return;
         }
         sched_yield();
         
         // if not in contended state, set to be in contended state
-        state = internal_exchange(this, 2);
+        state = internal_exchange( this, 2 );
         if ( !state ) return; // state == 0
         init_state = 2;
-        futex((int*)&val, FUTEX_WAIT, 2); // if val is not 2 this returns with EWOULDBLOCK
+        futex( (int*)&val, FUTEX_WAIT, 2 ); // if val is not 2 this returns with EWOULDBLOCK
     }
 }
@@ -276,43 +281,13 @@
 static inline void unlock( go_mutex & this ) with(this) {
 	// if uncontended do atomic unlock and then return
-    if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return;
+    if ( __atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1 ) return;
 	
 	// otherwise threads are blocked so we must wake one
-	futex((int *)&val, FUTEX_WAKE, 1);
-}
-
-static inline void on_notify( go_mutex & f, thread$ * t){ unpark(t); }
-static inline size_t on_wait( go_mutex & f ) {unlock(f); return 0;}
+	futex( (int *)&val, FUTEX_WAKE, 1 );
+}
+
+static inline void on_notify( go_mutex & f, thread$ * t){ unpark( t ); }
+static inline size_t on_wait( go_mutex & f ) { unlock( f ); park(); return 0; }
 static inline void on_wakeup( go_mutex & f, size_t recursion ) {}
-
-//-----------------------------------------------------------------------------
-// CLH Spinlock
-// - No recursive acquisition
-// - Needs to be released by owner
-
-struct clh_lock {
-	volatile bool * volatile tail;
-    volatile bool * volatile head;
-};
-
-static inline void  ?{}( clh_lock & this ) { this.tail = malloc(); *this.tail = true; }
-static inline void ^?{}( clh_lock & this ) { free(this.tail); }
-
-static inline void lock(clh_lock & l) {
-	thread$ * curr_thd = active_thread();
-	*(curr_thd->clh_node) = false;
-	volatile bool * prev = __atomic_exchange_n((bool **)(&l.tail), (bool *)(curr_thd->clh_node), __ATOMIC_SEQ_CST);
-	while(!__atomic_load_n(prev, __ATOMIC_SEQ_CST)) Pause();
-    __atomic_store_n((bool **)(&l.head), (bool *)curr_thd->clh_node, __ATOMIC_SEQ_CST);
-    curr_thd->clh_node = prev;
-}
-
-static inline void unlock(clh_lock & l) {
-	__atomic_store_n((bool *)(l.head), true, __ATOMIC_SEQ_CST);
-}
-
-static inline void on_notify(clh_lock & this, struct thread$ * t ) { unpark(t); }
-static inline size_t on_wait(clh_lock & this) { unlock(this); return 0; }
-static inline void on_wakeup(clh_lock & this, size_t recursion ) { lock(this); }
 
 //-----------------------------------------------------------------------------
@@ -337,15 +312,15 @@
 static inline void  ^?{}( exp_backoff_then_block_lock & this ){}
 
-static inline bool internal_try_lock(exp_backoff_then_block_lock & this, size_t & compare_val) with(this) {
+static inline bool internal_try_lock( exp_backoff_then_block_lock & this, size_t & compare_val ) with(this) {
 	return __atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
 }
 
-static inline bool try_lock(exp_backoff_then_block_lock & this) { size_t compare_val = 0; return internal_try_lock(this, compare_val); }
-
-static inline bool try_lock_contention(exp_backoff_then_block_lock & this) with(this) {
-	return !__atomic_exchange_n(&lock_value, 2, __ATOMIC_ACQUIRE);
-}
-
-static inline bool block(exp_backoff_then_block_lock & this) with(this) {
+static inline bool try_lock( exp_backoff_then_block_lock & this ) { size_t compare_val = 0; return internal_try_lock( this, compare_val ); }
+
+static inline bool try_lock_contention( exp_backoff_then_block_lock & this ) with(this) {
+	return !__atomic_exchange_n( &lock_value, 2, __ATOMIC_ACQUIRE );
+}
+
+static inline bool block( exp_backoff_then_block_lock & this ) with(this) {
     lock( spinlock __cfaabi_dbg_ctx2 );
     if (__atomic_load_n( &lock_value, __ATOMIC_SEQ_CST) != 2) {
@@ -359,5 +334,5 @@
 }
 
-static inline void lock(exp_backoff_then_block_lock & this) with(this) {
+static inline void lock( exp_backoff_then_block_lock & this ) with(this) {
 	size_t compare_val = 0;
 	int spin = 4;
@@ -378,5 +353,5 @@
 }
 
-static inline void unlock(exp_backoff_then_block_lock & this) with(this) {
+static inline void unlock( exp_backoff_then_block_lock & this ) with(this) {
     if (__atomic_exchange_n(&lock_value, 0, __ATOMIC_RELEASE) == 1) return;
     lock( spinlock __cfaabi_dbg_ctx2 );
@@ -386,7 +361,7 @@
 }
 
-static inline void on_notify(exp_backoff_then_block_lock & this, struct thread$ * t ) { unpark(t); }
-static inline size_t on_wait(exp_backoff_then_block_lock & this) { unlock(this); return 0; }
-static inline void on_wakeup(exp_backoff_then_block_lock & this, size_t recursion ) { lock(this); }
+static inline void on_notify( exp_backoff_then_block_lock & this, struct thread$ * t ) { unpark( t ); }
+static inline size_t on_wait( exp_backoff_then_block_lock & this ) { unlock( this ); park(); return 0; }
+static inline void on_wakeup( exp_backoff_then_block_lock & this, size_t recursion ) { lock( this ); }
 
 //-----------------------------------------------------------------------------
@@ -418,5 +393,5 @@
 
 // if this is called recursively IT WILL DEADLOCK!!!!!
-static inline void lock(fast_block_lock & this) with(this) {
+static inline void lock( fast_block_lock & this ) with(this) {
 	lock( lock __cfaabi_dbg_ctx2 );
 	if ( held ) {
@@ -430,5 +405,5 @@
 }
 
-static inline void unlock(fast_block_lock & this) with(this) {
+static inline void unlock( fast_block_lock & this ) with(this) {
 	lock( lock __cfaabi_dbg_ctx2 );
 	/* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this );
@@ -439,11 +414,11 @@
 }
 
-static inline void on_notify(fast_block_lock & this, struct thread$ * t ) with(this) {
+static inline void on_notify( fast_block_lock & this, struct thread$ * t ) with(this) {
     lock( lock __cfaabi_dbg_ctx2 );
     insert_last( blocked_threads, *t );
     unlock( lock );
 }
-static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; }
-static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { }
+static inline size_t on_wait( fast_block_lock & this) { unlock(this); park(); return 0; }
+static inline void on_wakeup( fast_block_lock & this, size_t recursion ) { }
 
 //-----------------------------------------------------------------------------
@@ -456,5 +431,5 @@
 struct simple_owner_lock {
 	// List of blocked threads
-	dlist( thread$ ) blocked_threads;
+	dlist( select_node ) blocked_threads;
 
 	// Spin lock used for mutual exclusion
@@ -477,6 +452,6 @@
 static inline void ?=?( simple_owner_lock & this, simple_owner_lock this2 ) = void;
 
-static inline void lock(simple_owner_lock & this) with(this) {
-	if (owner == active_thread()) {
+static inline void lock( simple_owner_lock & this ) with(this) {
+	if ( owner == active_thread() ) {
 		recursion_count++;
 		return;
@@ -484,6 +459,7 @@
 	lock( lock __cfaabi_dbg_ctx2 );
 
-	if (owner != 0p) {
-		insert_last( blocked_threads, *active_thread() );
+	if ( owner != 0p ) {
+        select_node node;
+		insert_last( blocked_threads, node );
 		unlock( lock );
 		park( );
@@ -495,13 +471,19 @@
 }
 
-// TODO: fix duplicate def issue and bring this back
-// void pop_and_set_new_owner( simple_owner_lock & this ) with( this ) {
-	// thread$ * t = &try_pop_front( blocked_threads );
-	// owner = t;
-	// recursion_count = ( t ? 1 : 0 );
-	// unpark( t );
-// }
-
-static inline void unlock(simple_owner_lock & this) with(this) {
+static inline void pop_node( simple_owner_lock & this ) with(this) {
+    __handle_waituntil_OR( blocked_threads );
+    select_node * node = &try_pop_front( blocked_threads );
+    if ( node ) {
+        owner = node->blocked_thread;
+        recursion_count = 1;
+        // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
+        wake_one( blocked_threads, *node );
+    } else {
+        owner = 0p;
+        recursion_count = 0;
+    }
+}
+
+static inline void unlock( simple_owner_lock & this ) with(this) {
 	lock( lock __cfaabi_dbg_ctx2 );
 	/* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
@@ -510,18 +492,14 @@
 	recursion_count--;
 	if ( recursion_count == 0 ) {
-		// pop_and_set_new_owner( this );
-		thread$ * t = &try_pop_front( blocked_threads );
-		owner = t;
-		recursion_count = ( t ? 1 : 0 );
-		unpark( t );
+		pop_node( this );
 	}
 	unlock( lock );
 }
 
-static inline void on_notify(simple_owner_lock & this, struct thread$ * t ) with(this) {
+static inline void on_notify(simple_owner_lock & this, thread$ * t ) with(this) {
 	lock( lock __cfaabi_dbg_ctx2 );
 	// lock held
 	if ( owner != 0p ) {
-		insert_last( blocked_threads, *t );
+		insert_last( blocked_threads, *(select_node *)t->link_node );
 	}
 	// lock not held
@@ -534,5 +512,5 @@
 }
 
-static inline size_t on_wait(simple_owner_lock & this) with(this) {
+static inline size_t on_wait( simple_owner_lock & this ) with(this) {
 	lock( lock __cfaabi_dbg_ctx2 );
 	/* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
@@ -541,16 +519,69 @@
 	size_t ret = recursion_count;
 
-	// pop_and_set_new_owner( this );
-
-	thread$ * t = &try_pop_front( blocked_threads );
-	owner = t;
-	recursion_count = ( t ? 1 : 0 );
-	unpark( t );
-
+	pop_node( this );
+
+    select_node node;
+    active_thread()->link_node = (void *)&node;
 	unlock( lock );
+    park();
+
 	return ret;
 }
 
-static inline void on_wakeup(simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; }
+static inline void on_wakeup( simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; }
+
+// waituntil() support
+static inline bool register_select( simple_owner_lock & this, select_node & node ) with(this) {
+    lock( lock __cfaabi_dbg_ctx2 );
+
+    // check if we can complete operation. If so race to establish winner in special OR case
+    if ( !node.park_counter && ( owner == active_thread() || owner == 0p ) ) {
+        if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering
+           unlock( lock );
+           return false;
+        }
+    }
+
+    if ( owner == active_thread() ) {
+		recursion_count++;
+        if ( node.park_counter ) __make_select_node_available( node );
+        unlock( lock );
+		return true;
+	}
+
+    if ( owner != 0p ) {
+		insert_last( blocked_threads, node );
+		unlock( lock );
+		return false;
+	}
+    
+	owner = active_thread();
+	recursion_count = 1;
+
+    if ( node.park_counter ) __make_select_node_available( node );
+    unlock( lock );
+    return true;
+}
+
+static inline bool unregister_select( simple_owner_lock & this, select_node & node ) with(this) {
+    lock( lock __cfaabi_dbg_ctx2 );
+    if ( node`isListed ) {
+        remove( node );
+        unlock( lock );
+        return false;
+    }
+
+    if ( owner == active_thread() ) {
+        recursion_count--;
+        if ( recursion_count == 0 ) {
+            pop_node( this );
+        }
+    }
+    unlock( lock );
+    return false;
+}
+
+static inline bool on_selected( simple_owner_lock & this, select_node & node ) { return true; }
+
 
 //-----------------------------------------------------------------------------
@@ -578,5 +609,5 @@
 
 // if this is called recursively IT WILL DEADLOCK!
-static inline void lock(spin_queue_lock & this) with(this) {
+static inline void lock( spin_queue_lock & this ) with(this) {
 	mcs_spin_node node;
 	lock( lock, node );
@@ -586,13 +617,13 @@
 }
 
-static inline void unlock(spin_queue_lock & this) with(this) {
+static inline void unlock( spin_queue_lock & this ) with(this) {
 	__atomic_store_n(&held, false, __ATOMIC_RELEASE);
 }
 
-static inline void on_notify(spin_queue_lock & this, struct thread$ * t ) {
+static inline void on_notify( spin_queue_lock & this, struct thread$ * t ) {
 	unpark(t);
 }
-static inline size_t on_wait(spin_queue_lock & this) { unlock(this); return 0; }
-static inline void on_wakeup(spin_queue_lock & this, size_t recursion ) { lock(this); }
+static inline size_t on_wait( spin_queue_lock & this ) { unlock( this ); park(); return 0; }
+static inline void on_wakeup( spin_queue_lock & this, size_t recursion ) { lock( this ); }
 
 
@@ -621,5 +652,5 @@
 
 // if this is called recursively IT WILL DEADLOCK!!!!!
-static inline void lock(mcs_block_spin_lock & this) with(this) {
+static inline void lock( mcs_block_spin_lock & this ) with(this) {
 	mcs_node node;
 	lock( lock, node );
@@ -633,7 +664,7 @@
 }
 
-static inline void on_notify(mcs_block_spin_lock & this, struct thread$ * t ) { unpark(t); }
-static inline size_t on_wait(mcs_block_spin_lock & this) { unlock(this); return 0; }
-static inline void on_wakeup(mcs_block_spin_lock & this, size_t recursion ) {lock(this); }
+static inline void on_notify( mcs_block_spin_lock & this, struct thread$ * t ) { unpark( t ); }
+static inline size_t on_wait( mcs_block_spin_lock & this) { unlock( this ); park(); return 0; }
+static inline void on_wakeup( mcs_block_spin_lock & this, size_t recursion ) {lock( this ); }
 
 //-----------------------------------------------------------------------------
@@ -661,5 +692,5 @@
 
 // if this is called recursively IT WILL DEADLOCK!!!!!
-static inline void lock(block_spin_lock & this) with(this) {
+static inline void lock( block_spin_lock & this ) with(this) {
 	lock( lock );
 	while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause();
@@ -668,9 +699,9 @@
 }
 
-static inline void unlock(block_spin_lock & this) with(this) {
+static inline void unlock( block_spin_lock & this ) with(this) {
 	__atomic_store_n(&held, false, __ATOMIC_RELEASE);
 }
 
-static inline void on_notify(block_spin_lock & this, struct thread$ * t ) with(this.lock) {
+static inline void on_notify( block_spin_lock & this, struct thread$ * t ) with(this.lock) {
 	// first we acquire internal fast_block_lock
 	lock( lock __cfaabi_dbg_ctx2 );
@@ -686,6 +717,6 @@
 	unpark(t);
 }
-static inline size_t on_wait(block_spin_lock & this) { unlock(this); return 0; }
-static inline void on_wakeup(block_spin_lock & this, size_t recursion ) with(this) {
+static inline size_t on_wait( block_spin_lock & this ) { unlock( this ); park(); return 0; }
+static inline void on_wakeup( block_spin_lock & this, size_t recursion ) with(this) {
 	// now we acquire the entire block_spin_lock upon waking up
 	while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause();
@@ -714,8 +745,4 @@
 forall(L & | is_blocking_lock(L)) {
 	struct info_thread;
-
-	// // for use by sequence
-	// info_thread(L) *& Back( info_thread(L) * this );
-	// info_thread(L) *& Next( info_thread(L) * this );
 }
 
