Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision a84306790d15c8aad8810aca4dca6b6598a82744)
+++ src/Concurrency/Keywords.cc	(revision 6bbce58bd62e0b1ff16a394dfb2a320dcf9ca898)
@@ -196,4 +196,5 @@
 		std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
 		void validate( DeclarationWithType * );
+		void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
 		void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
 
@@ -206,4 +207,5 @@
 	  	StructDecl* monitor_decl = nullptr;
 		StructDecl* guard_decl = nullptr;
+		StructDecl* dtor_guard_decl = nullptr;
 
 		static std::unique_ptr< Type > generic_func;
@@ -229,4 +231,5 @@
 
 		void postvisit( FunctionDecl * decl );
+		void previsit ( StructDecl   * decl );
 
 		void addStartStatement( FunctionDecl * decl, DeclarationWithType * param );
@@ -236,4 +239,8 @@
 			acceptAll( translationUnit, impl );
 		}
+
+	  private :
+		bool thread_ctor_seen = false;
+		StructDecl * thread_decl = nullptr;
 	};
 
@@ -403,4 +410,10 @@
 		if( mutexArgs.empty() ) return;
 
+		if( CodeGen::isConstructor(decl->name) ) throw SemanticError( "constructors cannot have mutex parameters", decl );
+
+		bool isDtor = CodeGen::isDestructor( decl->name );
+
+		if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( "destructors can only have 1 mutex argument", decl );
+
 		for(auto arg : mutexArgs) {
 			validate( arg );
@@ -412,6 +425,12 @@
 		if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
 		if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
-
-		addStatments( decl, body, mutexArgs );
+		if( !dtor_guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
+
+		if( isDtor ) {
+			addDtorStatments( decl, body, mutexArgs );
+		}
+		else {
+			addStatments( decl, body, mutexArgs );
+		}
 	}
 
@@ -425,4 +444,8 @@
 			assert( !guard_decl );
 			guard_decl = decl;
+		}
+		else if( decl->name == "monitor_dtor_guard_t" ) {
+			assert( !dtor_guard_decl );
+			dtor_guard_decl = decl;
 		}
 	}
@@ -457,4 +480,55 @@
 		//Make sure that typed isn't mutex
 		if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
+	}
+
+	void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
+		Type * arg_type = args.front()->get_type()->clone();
+		arg_type->set_mutex( false );
+
+		ObjectDecl * monitors = new ObjectDecl(
+			"__monitor",
+			noStorage,
+			LinkageSpec::Cforall,
+			nullptr,
+			new PointerType(
+				noQualifiers,
+				new StructInstType(
+					noQualifiers,
+					monitor_decl
+				)
+			),
+			new SingleInit( new UntypedExpr(
+				new NameExpr( "get_monitor" ),
+				{  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
+			))
+		);
+
+		assert(generic_func);
+
+		//in reverse order :
+		// monitor_guard_t __guard = { __monitors, #, func };
+		body->push_front(
+			new DeclStmt( noLabels, new ObjectDecl(
+				"__guard",
+				noStorage,
+				LinkageSpec::Cforall,
+				nullptr,
+				new StructInstType(
+					noQualifiers,
+					dtor_guard_decl
+				),
+				new ListInit(
+					{
+						new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
+						new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
+					},
+					noDesignators,
+					true
+				)
+			))
+		);
+
+		//monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
+		body->push_front( new DeclStmt( noLabels, monitors) );
 	}
 
@@ -523,10 +597,27 @@
 	// General entry routine
 	//=============================================================================================
+	void ThreadStarter::previsit( StructDecl * decl ) {
+		if( decl->name == "thread_desc" && decl->body ) {
+			assert( !thread_decl );
+			thread_decl = decl;
+		}
+	}
+
 	void ThreadStarter::postvisit(FunctionDecl * decl) {
 		if( ! CodeGen::isConstructor(decl->name) ) return;
+
+		Type * typeof_this = InitTweak::getTypeofThis(decl->type);
+		StructInstType * ctored_type = dynamic_cast< StructInstType * >( typeof_this );
+		if( ctored_type && ctored_type->baseStruct == thread_decl ) {
+			thread_ctor_seen = true;
+		}
 
 		DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
 		auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
 		if( type && type->get_baseStruct()->is_thread() ) {
+			if( !thread_decl || !thread_ctor_seen ) {
+				throw SemanticError("thread keyword requires threads to be in scope, add #include <thread>");
+			}
+
 			addStartStatement( decl, param );
 		}
