Index: libcfa/src/concurrency/monitor.cfa
===================================================================
--- libcfa/src/concurrency/monitor.cfa	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
+++ libcfa/src/concurrency/monitor.cfa	(revision 2aa25cc246cb459caed9ef2620e76d91b5dca91d)
@@ -89,5 +89,8 @@
 	__cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
 
-	if( !this->owner ) {
+	if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) {
+		abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this );
+	}
+	else if( !this->owner ) {
 		// No one has the monitor, just take it
 		__set_owner( this, thrd );
@@ -137,5 +140,5 @@
 }
 
-static void __dtor_enter( $monitor * this, fptr_t func ) {
+static void __dtor_enter( $monitor * this, fptr_t func, bool join ) {
 	// Lock the monitor spinlock
 	lock( this->lock __cfaabi_dbg_ctx2 );
@@ -157,8 +160,22 @@
 		return;
 	}
-	else if( this->owner == thrd) {
+	else if( this->owner == thrd && !join) {
 		// We already have the monitor... but where about to destroy it so the nesting will fail
 		// Abort!
 		abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
+	}
+	// SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check
+	// to avoid that it sets the owner to the special value thrd | 1p before exiting
+	else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) {
+		// restore the owner and just return
+		__cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
+
+		// No one has the monitor, just take it
+		this->owner = thrd;
+
+		verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
+
+		unlock( this->lock );
+		return;
 	}
 
@@ -251,13 +268,15 @@
 
 // Leave single monitor for the last time
-void __dtor_leave( $monitor * this ) {
+void __dtor_leave( $monitor * this, bool join ) {
 	__cfaabi_dbg_debug_do(
 		if( TL_GET( this_thread ) != this->owner ) {
 			abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
 		}
-		if( this->recursion != 1 ) {
+		if( this->recursion != 1  && !join ) {
 			abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
 		}
 	)
+
+	this->owner = ($thread*)(1 | (uintptr_t)this->owner);
 }
 
@@ -307,4 +326,15 @@
 }
 
+// Join a thread
+forall( dtype T | is_thread(T) )
+T & join( T & this ) {
+	$monitor *    m = get_monitor(this);
+	void (*dtor)(T& mutex this) = ^?{};
+	monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
+	{
+		return this;
+	}
+}
+
 // Enter multiple monitor
 // relies on the monitor array being sorted
@@ -366,5 +396,5 @@
 // Ctor for monitor guard
 // Sorts monitors before entering
-void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
+void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) {
 	// optimization
 	$thread * thrd = TL_GET( this_thread );
@@ -376,8 +406,11 @@
 	this.prev = thrd->monitors;
 
+	// Save whether we are in a join or not
+	this.join = join;
+
 	// Update thread context (needed for conditions)
 	(thrd->monitors){m, 1, func};
 
-	__dtor_enter( this.m, func );
+	__dtor_enter( this.m, func, join );
 }
 
@@ -385,5 +418,5 @@
 void ^?{}( monitor_dtor_guard_t & this ) {
 	// Leave the monitors in order
-	__dtor_leave( this.m );
+	__dtor_leave( this.m, this.join );
 
 	// Restore thread context
Index: libcfa/src/concurrency/monitor.hfa
===================================================================
--- libcfa/src/concurrency/monitor.hfa	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
+++ libcfa/src/concurrency/monitor.hfa	(revision 2aa25cc246cb459caed9ef2620e76d91b5dca91d)
@@ -53,7 +53,8 @@
 	$monitor *    m;
 	__monitor_group_t prev;
+	bool join;
 };
 
-void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );
+void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)(), bool join );
 void ^?{}( monitor_dtor_guard_t & this );
 
Index: libcfa/src/concurrency/thread.hfa
===================================================================
--- libcfa/src/concurrency/thread.hfa	(revision 1c01c5836c12d14d4c519d76550c0381bc562aaf)
+++ libcfa/src/concurrency/thread.hfa	(revision 2aa25cc246cb459caed9ef2620e76d91b5dca91d)
@@ -106,4 +106,9 @@
 void sleep( Duration duration );
 
+//----------
+// join
+forall( dtype T | is_thread(T) )
+T & join( T & this );
+
 // Local Variables: //
 // mode: c //
