Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision c5328475c954a0cf10db09a145ba92efc50823c8)
+++ src/Concurrency/Keywords.cc	(revision ab8c6a6efe9f4120bf5d5eed0b649cad34d89af3)
@@ -46,4 +46,12 @@
 	}
 
+	// Only detects threads constructed with the keyword thread.
+	inline static bool isThread( DeclarationWithType * decl ) {
+		Type * baseType = decl->get_type()->stripDeclarator();
+		StructInstType * instType = dynamic_cast<StructInstType *>( baseType );
+		if ( nullptr == instType ) { return false; }
+		return instType->baseStruct->is_thread();
+	}
+
 	//=============================================================================================
 	// Pass declarations
@@ -119,5 +127,5 @@
 			"get_thread",
 			"thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
-			"",
+			"ThreadCancelled",
 			true,
 			AggregateDecl::Thread
@@ -290,6 +298,7 @@
 		std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
 		void validate( DeclarationWithType * );
-		void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
-		void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
+		void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
+		void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
+		void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
 
 		static void implement( std::list< Declaration * > & translationUnit ) {
@@ -302,4 +311,5 @@
 		StructDecl* guard_decl = nullptr;
 		StructDecl* dtor_guard_decl = nullptr;
+		StructDecl* thread_guard_decl = nullptr;
 
 		static std::unique_ptr< Type > generic_func;
@@ -801,5 +811,5 @@
 		bool first = false;
 		std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
-		bool isDtor = CodeGen::isDestructor( decl->name );
+		bool const isDtor = CodeGen::isDestructor( decl->name );
 
 		// Is this function relevant to monitors
@@ -849,9 +859,15 @@
 
 		// Instrument the body
-		if( isDtor ) {
-			addDtorStatments( decl, body, mutexArgs );
+		if ( isDtor && isThread( mutexArgs.front() ) ) {
+			if( !thread_guard_decl ) {
+				SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
+			}
+			addThreadDtorStatements( decl, body, mutexArgs );
+		}
+		else if ( isDtor ) {
+			addDtorStatements( decl, body, mutexArgs );
 		}
 		else {
-			addStatments( decl, body, mutexArgs );
+			addStatements( decl, body, mutexArgs );
 		}
 	}
@@ -870,4 +886,8 @@
 			assert( !dtor_guard_decl );
 			dtor_guard_decl = decl;
+		}
+		else if( decl->name == "thread_dtor_guard_t" && decl->body ) {
+			assert( !thread_guard_decl );
+			thread_guard_decl = decl;
 		}
 	}
@@ -908,5 +928,5 @@
 	}
 
-	void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
+	void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
 		Type * arg_type = args.front()->get_type()->clone();
 		arg_type->set_mutex( false );
@@ -957,8 +977,44 @@
 
 		//$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
-		body->push_front( new DeclStmt( monitors) );
-	}
-
-	void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
+		body->push_front( new DeclStmt( monitors ) );
+	}
+
+	void MutexKeyword::addThreadDtorStatements(
+			FunctionDecl*, CompoundStmt * body,
+			const std::list<DeclarationWithType * > & args ) {
+		assert( args.size() == 1 );
+		DeclarationWithType * arg = args.front();
+		Type * arg_type = arg->get_type()->clone();
+		assert( arg_type->get_mutex() );
+		arg_type->set_mutex( false );
+
+		// thread_dtor_guard_t __guard = { this, intptr( 0 ) };
+		body->push_front(
+			new DeclStmt( new ObjectDecl(
+				"__guard",
+				noStorageClasses,
+				LinkageSpec::Cforall,
+				nullptr,
+				new StructInstType(
+					noQualifiers,
+					thread_guard_decl
+				),
+				new ListInit(
+					{
+						new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ),
+						new SingleInit( new UntypedExpr(
+							new NameExpr( "intptr" ), {
+								new ConstantExpr( Constant::from_int( 0 ) ),
+							}
+						) ),
+					},
+					noDesignators,
+					true
+				)
+			))
+		);
+	}
+
+	void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
 		ObjectDecl * monitors = new ObjectDecl(
 			"__monitors",
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision c5328475c954a0cf10db09a145ba92efc50823c8)
+++ src/GenPoly/Specialize.cc	(revision ab8c6a6efe9f4120bf5d5eed0b649cad34d89af3)
@@ -321,7 +321,21 @@
 	}
 
+	// Fold it into Specialize if we find a good way.
+	struct StaticThunks final : public WithShortCircuiting {
+		void previsit( Declaration * ) {
+			visit_children = false;
+		}
+		void postvisit( FunctionDecl * decl ) {
+			if ( isPrefix( decl->name, "_thunk" ) ) {
+				decl->storageClasses.is_static = true;
+			}
+		}
+	};
+
 	void convertSpecializations( std::list< Declaration* >& translationUnit ) {
 		PassVisitor<Specialize> spec;
 		mutateAll( translationUnit, spec );
+		PassVisitor<StaticThunks> staticThunks;
+		acceptAll( translationUnit, staticThunks );
 	}
 } // namespace GenPoly
