Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/CodeGen/CodeGenerator.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -172,4 +172,6 @@
 	// *** Declarations
 	void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
+		// deleted decls should never be used, so don't print them
+		if ( functionDecl->isDeleted && genC ) return;
 		extension( functionDecl );
 		genAttributes( functionDecl->get_attributes() );
@@ -185,7 +187,12 @@
 			functionDecl->get_statements()->accept( *visitor );
 		} // if
+		if ( functionDecl->isDeleted ) {
+			output << " = void";
+		}
 	}
 
 	void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
+		// deleted decls should never be used, so don't print them
+		if ( objectDecl->isDeleted && genC ) return;
 		if (objectDecl->get_name().empty() && genC ) {
 			// only generate an anonymous name when generating C code, otherwise it clutters the output too much
@@ -206,4 +213,7 @@
 			objectDecl->get_init()->accept( *visitor );
 		} // if
+		if ( objectDecl->isDeleted ) {
+			output << " = void";
+		}
 
 		if ( objectDecl->get_bitfieldWidth() ) {
@@ -827,4 +837,27 @@
 		expr->expr->accept( *visitor );
 	}
+
+	void CodeGenerator::postvisit( GenericExpr * expr ) {
+		assertf( ! genC, "C11 _Generic expressions should not reach code generation." );
+		output << "_Generic(";
+		expr->control->accept( *visitor );
+		output << ", ";
+		unsigned int numAssocs = expr->associations.size();
+		unsigned int i = 0;
+		for ( GenericExpr::Association & assoc : expr->associations ) {
+			if (assoc.isDefault) {
+				output << "default: ";
+			} else {
+				output << genType( assoc.type, "", pretty, genC ) << ": ";
+			}
+			assoc.expr->accept( *visitor );
+			if ( i+1 != numAssocs ) {
+				output << ", ";
+			}
+			i++;
+		}
+		output << ")";
+	}
+
 
 	// *** Statements
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/CodeGen/CodeGenerator.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -94,4 +94,5 @@
 		void postvisit( ConstructorExpr * );
 		void postvisit( DeletedExpr * );
+		void postvisit( GenericExpr * );
 
 		//*** Statements
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Common/PassVisitor.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -125,4 +125,5 @@
 	virtual void visit( InitExpr *  initExpr ) override final;
 	virtual void visit( DeletedExpr *  delExpr ) override final;
+	virtual void visit( GenericExpr * genExpr ) override final;
 
 	virtual void visit( VoidType * basicType ) override final;
@@ -223,4 +224,5 @@
 	virtual Expression * mutate( InitExpr *  initExpr ) override final;
 	virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
+	virtual Expression * mutate( GenericExpr * genExpr ) override final;
 
 	virtual Type * mutate( VoidType * basicType ) override final;
@@ -311,5 +313,5 @@
 	void indexerAddUnionFwd ( UnionDecl                 * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
 	void indexerAddTrait    ( TraitDecl                 * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
-	void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith     ( pass, 0, exprs, withStmt ); }
+	void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith( pass, 0, exprs, withStmt ); }
 
 
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Common/PassVisitor.impl.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -2073,4 +2073,35 @@
 
 //--------------------------------------------------------------------------
+// GenericExpr
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( GenericExpr * node ) {
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept_impl( node->control, *this );
+	for ( GenericExpr::Association & assoc : node->associations ) {
+		indexerScopedAccept( assoc.type, *this );
+		maybeAccept_impl( assoc.expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( GenericExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env, *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutate_impl( node->control, *this );
+	for ( GenericExpr::Association & assoc : node->associations ) {
+		indexerScopedMutate( assoc.type, *this );
+		maybeMutate_impl( assoc.expr, *this );
+	}
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
 // VoidType
 template< typename pass_type >
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Concurrency/Keywords.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -443,22 +443,52 @@
 		bool first = false;
 		std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
-		if( mutexArgs.empty() ) return;
-
-		if( CodeGen::isConstructor(decl->name) && first ) SemanticError( decl, "constructors cannot have mutex parameters" );
-
 		bool isDtor = CodeGen::isDestructor( decl->name );
 
+		// Is this function relevant to monitors
+		if( mutexArgs.empty() ) {
+			// If this is the destructor for a monitor it must be mutex
+			if(isDtor) {
+				Type* ty = decl->get_functionType()->get_parameters().front()->get_type();
+
+				// If it's a copy, it's not a mutex
+				ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
+				if( ! rty ) return;
+
+				// If we are not pointing directly to a type, it's not a mutex
+				Type* base = rty->get_base();
+				if( dynamic_cast< ReferenceType * >( base ) ) return;
+				if( dynamic_cast< PointerType * >( base ) ) return;
+
+				// Check if its a struct
+				StructInstType * baseStruct = dynamic_cast< StructInstType * >( base );
+				if( !baseStruct ) return;
+
+				// Check if its a monitor
+				if(baseStruct->baseStruct->is_monitor() || baseStruct->baseStruct->is_thread())
+					SemanticError( decl, "destructors for structures declared as \"monitor\" must use mutex parameters\n" );
+			}
+			return;
+		}
+
+		// Monitors can't be constructed with mutual exclusion
+		if( CodeGen::isConstructor(decl->name) && !first ) SemanticError( decl, "constructors cannot have mutex parameters" );
+
+		// It makes no sense to have multiple mutex parameters for the destructor
 		if( isDtor && mutexArgs.size() != 1 ) SemanticError( decl, "destructors can only have 1 mutex argument" );
 
+		// Make sure all the mutex arguments are monitors
 		for(auto arg : mutexArgs) {
 			validate( arg );
 		}
 
+		// Check if we need to instrument the body
 		CompoundStmt* body = decl->get_statements();
 		if( ! body ) return;
 
+		// Do we have the required headers
 		if( !monitor_decl || !guard_decl || !dtor_guard_decl )
-			SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
-
+			SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>\n" );
+
+		// Instrument the body
 		if( isDtor ) {
 			addDtorStatments( decl, body, mutexArgs );
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Parser/DeclarationNode.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -1067,5 +1067,11 @@
 			SemanticError( this, "invalid function specifier for " );
 		} // if
-		return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
+		bool isDelete = initializer && initializer->get_isDelete();
+		Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
+		if ( isDelete ) {
+			DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl );
+			dwt->isDeleted = true;
+		}
+		return decl;
 	} // if
 
Index: src/Parser/InitializerNode.cc
===================================================================
--- src/Parser/InitializerNode.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Parser/InitializerNode.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -27,5 +27,5 @@
 
 InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des )
-		: expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ) {
+		: expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
 	if ( aggrp )
 		kids = dynamic_cast< InitializerNode * >( get_next() );
@@ -36,5 +36,5 @@
 
 InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des )
-		: expr( nullptr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ) {
+		: expr( nullptr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
 	if ( init )
 		set_last( init );
@@ -46,4 +46,6 @@
 		set_next( nullptr );
 } // InitializerNode::InitializerNode
+
+InitializerNode::InitializerNode( bool isDelete ) : expr( nullptr ), aggregate( false ), designator( nullptr ), kids( nullptr ), maybeConstructed( false ), isDelete( isDelete ) {}
 
 InitializerNode::~InitializerNode() {
@@ -84,4 +86,5 @@
 
 Initializer * InitializerNode::build() const {
+	assertf( ! isDelete, "Should not build delete stmt InitializerNode" );
 	if ( aggregate ) {
 		// steal designators from children
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Parser/ParseNode.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -87,4 +87,5 @@
 	InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode * des = nullptr );
 	InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
+	InitializerNode( bool isDelete );
 	~InitializerNode();
 	virtual InitializerNode * clone() const { assert( false ); return nullptr; }
@@ -97,4 +98,6 @@
 	InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }
 	bool get_maybeConstructed() const { return maybeConstructed; }
+
+	bool get_isDelete() const { return isDelete; }
 
 	InitializerNode * next_init() const { return kids; }
@@ -110,4 +113,5 @@
 	InitializerNode * kids;
 	bool maybeConstructed;
+	bool isDelete;
 }; // InitializerNode
 
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Parser/TypeData.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -65,4 +65,5 @@
 	  case Aggregate:
 		// aggregate = new Aggregate_t;
+		aggregate.kind = DeclarationNode::NoAggregate;
 		aggregate.name = nullptr;
 		aggregate.params = nullptr;
@@ -70,4 +71,6 @@
 		aggregate.fields = nullptr;
 		aggregate.body = false;
+		aggregate.tagged = false;
+		aggregate.parent = nullptr;
 		break;
 	  case AggregateInst:
@@ -198,9 +201,9 @@
 		break;
 	  case Aggregate:
+		newtype->aggregate.kind = aggregate.kind;
 		newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
 		newtype->aggregate.params = maybeClone( aggregate.params );
 		newtype->aggregate.actuals = maybeClone( aggregate.actuals );
 		newtype->aggregate.fields = maybeClone( aggregate.fields );
-		newtype->aggregate.kind = aggregate.kind;
 		newtype->aggregate.body = aggregate.body;
 		newtype->aggregate.tagged = aggregate.tagged;
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/Parser/parser.yy	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -175,4 +175,5 @@
 	bool flag;
 	CatchStmt::Kind catch_kind;
+	GenericExpr * genexpr;
 }
 
@@ -259,4 +260,5 @@
 %type<flag> asm_volatile_opt
 %type<en> handler_predicate_opt
+%type<genexpr> generic_association generic_assoc_list
 
 // statements
@@ -501,15 +503,30 @@
 		{ SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
 	| GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
-		{ SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; }
+		{
+			// add the missing control expression to the GenericExpr and return it
+			$5->control = maybeMoveBuild<Expression>( $3 );
+			$$ = new ExpressionNode( $5 );
+		}
 	;
 
 generic_assoc_list:										// C11
-	| generic_association
+	generic_association
 	| generic_assoc_list ',' generic_association
+		{
+			// steal the association node from the singleton and delete the wrapper
+			$1->associations.splice($1->associations.end(), $3->associations);
+			delete $3;
+			$$ = $1;
+		}
 	;
 
 generic_association:									// C11
 	type_no_function ':' assignment_expression
+		{
+			// create a GenericExpr wrapper with one association pair
+			$$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>($3) } } );
+		}
 	| DEFAULT ':' assignment_expression
+		{ $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>($3) } } ); }
 	;
 
@@ -2081,5 +2098,5 @@
 		{ $$ = $2; }
 	| '=' VOID
-		{ $$ = nullptr; }
+		{ $$ = new InitializerNode( true ); }
 	| ATassign initializer
 		{ $$ = $2->set_maybeConstructed( false ); }
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -97,4 +97,5 @@
 		void postvisit( InitExpr * initExpr );
 		void postvisit( DeletedExpr * delExpr );
+		void postvisit( GenericExpr * genExpr );
 
 		/// Adds alternatives for anonymous members
@@ -1756,4 +1757,8 @@
 		assertf( false, "AlternativeFinder should never see a DeletedExpr." );
 	}
+
+	void AlternativeFinder::Finder::postvisit( GenericExpr * ) {
+		assertf( false, "_Generic is not yet supported." );
+	}
 } // namespace ResolvExpr
 
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SymTab/Indexer.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -148,5 +148,5 @@
 		for ( auto decl : copy ) {
 			if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
-				std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
+				std::list< DeclarationWithType * > & params = function->type->parameters;
 				assert( ! params.empty() );
 				// use base type of pointer, so that qualifiers on the pointer type aren't considered.
@@ -170,5 +170,5 @@
 				bool noUserDefinedFunc = ! val.existsUserDefinedFunc;
 				bool isUserDefinedFunc = ball.isUserDefinedFunc;
-				bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl.id->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
+				bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl.id->linkage == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
 				bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator
 				bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor;
@@ -471,5 +471,5 @@
 	void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
 		// default handling of conflicts is to raise an error
-		addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr );
+		addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );
 	}
 
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SymTab/Mangler.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -171,6 +171,6 @@
 					"w",	// SignedInt128
 					"Uw",	// UnsignedInt128
-					"a",   // Float80
-					"A",   // Float128
+					"x",   // Float80
+					"y",   // Float128
 				};
 				static_assert(
@@ -225,8 +225,8 @@
 				GuardValue( inFunctionType );
 				inFunctionType = true;
-				std::list< Type* > returnTypes = getTypes( functionType->get_returnVals() );
+				std::list< Type* > returnTypes = getTypes( functionType->returnVals );
 				acceptAll( returnTypes, *visitor );
 				mangleName << "_";
-				std::list< Type* > paramTypes = getTypes( functionType->get_parameters() );
+				std::list< Type* > paramTypes = getTypes( functionType->parameters );
 				acceptAll( paramTypes, *visitor );
 				mangleName << "_";
@@ -236,14 +236,14 @@
 				printQualifiers( refType );
 
-				mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name();
+				mangleName << ( refType->name.length() + prefix.length() ) << prefix << refType->name;
 
 				if ( mangleGenericParams ) {
-					std::list< Expression* >& params = refType->get_parameters();
+					std::list< Expression* >& params = refType->parameters;
 					if ( ! params.empty() ) {
 						mangleName << "_";
 						for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
 							TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-							assertf(paramType, "Aggregate parameters should be type expressions: %s", toString(*param).c_str());
-							maybeAccept( paramType->get_type(), *visitor );
+							assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
+							maybeAccept( paramType->type, *visitor );
 						}
 						mangleName << "_";
Index: src/SynTree/Declaration.cc
===================================================================
--- src/SynTree/Declaration.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SynTree/Declaration.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -104,4 +104,5 @@
 }
 
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SynTree/Declaration.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -84,4 +84,5 @@
 	Expression *asmName;
 	std::list< Attribute * > attributes;
+	bool isDeleted = false;
 
 	DeclarationWithType( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage, const std::list< Attribute * > & attributes, Type::FuncSpecifiers fs );
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SynTree/Expression.cc	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -748,4 +748,38 @@
 }
 
+GenericExpr::Association::Association( Type * type, Expression * expr ) : type( type ), expr( expr ), isDefault( false ) {}
+GenericExpr::Association::Association( Expression * expr ) : type( nullptr ), expr( expr ), isDefault( true ) {}
+GenericExpr::Association::Association( const Association & other ) : type( maybeClone( other.type ) ), expr( maybeClone( other.expr ) ), isDefault( other.isDefault ) {}
+GenericExpr::Association::~Association() {
+	delete type;
+	delete expr;
+}
+
+GenericExpr::GenericExpr( Expression * control, const std::list<Association> & assoc ) : Expression(), control( control ), associations( assoc ) {}
+GenericExpr::GenericExpr( const GenericExpr & other ) : Expression(other), control( maybeClone( other.control ) ), associations( other.associations ) {
+}
+GenericExpr::~GenericExpr() {
+	delete control;
+}
+
+void GenericExpr::print( std::ostream & os, Indenter indent ) const {
+	os << "C11 _Generic Expression" << std::endl << indent+1;
+	control->print( os, indent+1 );
+	os << std::endl << indent+1 << "... with associations: " << std::endl;
+	for ( const Association & assoc : associations ) {
+		os << indent+1;
+		if (assoc.isDefault) {
+			os << "... default: ";
+			assoc.expr->print( os, indent+1 );
+		} else {
+			os << "... type: ";
+			assoc.type->print( os, indent+1 );
+			os << std::endl << indent+1 << "... expression: ";
+			assoc.expr->print( os, indent+1 );
+			os << std::endl;
+		}
+		os << std::endl;
+	}
+}
 
 // Local Variables: //
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SynTree/Expression.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -865,4 +865,32 @@
 };
 
+/// C11 _Generic expression
+class GenericExpr : public Expression {
+public:
+	struct Association {
+		Type * type = nullptr;
+		Expression * expr = nullptr;
+		bool isDefault = false;
+
+		Association( Type * type, Expression * expr );
+		Association( Expression * expr );
+		Association( const Association & other );
+		Association & operator=( const Association & other ) = delete; // at the moment this isn't used, and I don't want to implement it
+		~Association();
+	};
+
+	Expression * control;
+	std::list<Association> associations;
+
+	GenericExpr( Expression * control, const std::list<Association> & assoc );
+	GenericExpr( const GenericExpr & other );
+	virtual ~GenericExpr();
+
+	virtual GenericExpr * clone() const { return new GenericExpr( * this ); }
+	virtual void accept( Visitor & v ) { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+};
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SynTree/Mutator.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -93,4 +93,5 @@
 	virtual Expression * mutate( InitExpr  * initExpr ) = 0;
 	virtual Expression * mutate( DeletedExpr * delExpr ) = 0;
+	virtual Expression * mutate( GenericExpr * genExpr ) = 0;
 
 	virtual Type * mutate( VoidType * basicType ) = 0;
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SynTree/SynTree.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -101,4 +101,5 @@
 class InitExpr;
 class DeletedExpr;
+class GenericExpr;
 
 class Type;
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/SynTree/Visitor.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -95,4 +95,5 @@
 	virtual void visit( InitExpr *  initExpr ) = 0;
 	virtual void visit( DeletedExpr * delExpr ) = 0;
+	virtual void visit( GenericExpr * genExpr ) = 0;
 
 	virtual void visit( VoidType * basicType ) = 0;
Index: src/benchmark/Makefile.am
===================================================================
--- src/benchmark/Makefile.am	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/benchmark/Makefile.am	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -277,8 +277,8 @@
 
 compile-io$(EXEEXT):
-	@${CC} -quiet -fsyntax-only -w ../tests/io.c					@CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
+	@${CC} -quiet -fsyntax-only -w ../tests/io1.c				@CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
 
 compile-monitor$(EXEEXT):
-	@${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c		@CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
+	@${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c	@CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
 
 compile-operators$(EXEEXT):
@@ -289,4 +289,4 @@
 
 compile-typeof$(EXEEXT):
-	@${CC} -quiet -fsyntax-only -w ../tests/typeof.c				@CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
-
+	@${CC} -quiet -fsyntax-only -w ../tests/typeof.c			@CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
+
Index: src/libcfa/Makefile.am
===================================================================
--- src/libcfa/Makefile.am	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/Makefile.am	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -51,5 +51,5 @@
 # not all platforms support concurrency, add option do disable it
 if BUILD_CONCURRENCY
-headers += concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor
+headers += concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor concurrency/mutex
 endif
 
Index: src/libcfa/Makefile.in
===================================================================
--- src/libcfa/Makefile.in	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/Makefile.in	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -97,5 +97,5 @@
 
 # not all platforms support concurrency, add option do disable it
-@BUILD_CONCURRENCY_TRUE@am__append_3 = concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor
+@BUILD_CONCURRENCY_TRUE@am__append_3 = concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor concurrency/mutex
 
 # not all platforms support concurrency, add option do disable it
@@ -153,13 +153,14 @@
 	containers/pair.c containers/result.c containers/vector.c \
 	concurrency/coroutine.c concurrency/thread.c \
-	concurrency/kernel.c concurrency/monitor.c assert.c \
-	exception.c virtual.c concurrency/CtxSwitch-@MACHINE_TYPE@.S \
-	concurrency/alarm.c concurrency/invoke.c \
-	concurrency/preemption.c
+	concurrency/kernel.c concurrency/monitor.c concurrency/mutex.c \
+	assert.c exception.c virtual.c \
+	concurrency/CtxSwitch-@MACHINE_TYPE@.S concurrency/alarm.c \
+	concurrency/invoke.c concurrency/preemption.c
 am__dirstamp = $(am__leading_dot)dirstamp
 @BUILD_CONCURRENCY_TRUE@am__objects_1 = concurrency/libcfa_d_a-coroutine.$(OBJEXT) \
 @BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_d_a-thread.$(OBJEXT) \
 @BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_d_a-kernel.$(OBJEXT) \
-@BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_d_a-monitor.$(OBJEXT)
+@BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_d_a-monitor.$(OBJEXT) \
+@BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_d_a-mutex.$(OBJEXT)
 am__objects_2 = libcfa_d_a-fstream.$(OBJEXT) \
 	libcfa_d_a-iostream.$(OBJEXT) libcfa_d_a-iterator.$(OBJEXT) \
@@ -188,12 +189,13 @@
 	containers/result.c containers/vector.c \
 	concurrency/coroutine.c concurrency/thread.c \
-	concurrency/kernel.c concurrency/monitor.c assert.c \
-	exception.c virtual.c concurrency/CtxSwitch-@MACHINE_TYPE@.S \
-	concurrency/alarm.c concurrency/invoke.c \
-	concurrency/preemption.c
+	concurrency/kernel.c concurrency/monitor.c concurrency/mutex.c \
+	assert.c exception.c virtual.c \
+	concurrency/CtxSwitch-@MACHINE_TYPE@.S concurrency/alarm.c \
+	concurrency/invoke.c concurrency/preemption.c
 @BUILD_CONCURRENCY_TRUE@am__objects_5 = concurrency/libcfa_a-coroutine.$(OBJEXT) \
 @BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_a-thread.$(OBJEXT) \
 @BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_a-kernel.$(OBJEXT) \
-@BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_a-monitor.$(OBJEXT)
+@BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_a-monitor.$(OBJEXT) \
+@BUILD_CONCURRENCY_TRUE@	concurrency/libcfa_a-mutex.$(OBJEXT)
 am__objects_6 = libcfa_a-fstream.$(OBJEXT) libcfa_a-iostream.$(OBJEXT) \
 	libcfa_a-iterator.$(OBJEXT) libcfa_a-limits.$(OBJEXT) \
@@ -264,7 +266,7 @@
 	containers/result containers/vector concurrency/coroutine \
 	concurrency/thread concurrency/kernel concurrency/monitor \
-	${shell find stdhdr -type f -printf "%p "} math gmp time_t.h \
-	clock bits/align.h bits/containers.h bits/defs.h bits/debug.h \
-	bits/locks.h concurrency/invoke.h
+	concurrency/mutex ${shell find stdhdr -type f -printf "%p "} \
+	math gmp time_t.h clock bits/align.h bits/containers.h \
+	bits/defs.h bits/debug.h bits/locks.h concurrency/invoke.h
 HEADERS = $(nobase_cfa_include_HEADERS)
 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
@@ -548,4 +550,6 @@
 concurrency/libcfa_d_a-monitor.$(OBJEXT): concurrency/$(am__dirstamp) \
 	concurrency/$(DEPDIR)/$(am__dirstamp)
+concurrency/libcfa_d_a-mutex.$(OBJEXT): concurrency/$(am__dirstamp) \
+	concurrency/$(DEPDIR)/$(am__dirstamp)
 concurrency/CtxSwitch-@MACHINE_TYPE@.$(OBJEXT):  \
 	concurrency/$(am__dirstamp) \
@@ -580,4 +584,6 @@
 	concurrency/$(DEPDIR)/$(am__dirstamp)
 concurrency/libcfa_a-monitor.$(OBJEXT): concurrency/$(am__dirstamp) \
+	concurrency/$(DEPDIR)/$(am__dirstamp)
+concurrency/libcfa_a-mutex.$(OBJEXT): concurrency/$(am__dirstamp) \
 	concurrency/$(DEPDIR)/$(am__dirstamp)
 concurrency/libcfa_a-alarm.$(OBJEXT): concurrency/$(am__dirstamp) \
@@ -635,4 +641,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-kernel.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-monitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-mutex.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-preemption.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-thread.Po@am__quote@
@@ -642,4 +649,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-kernel.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-monitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-mutex.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-preemption.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-thread.Po@am__quote@
@@ -930,4 +938,18 @@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_d_a-monitor.obj `if test -f 'concurrency/monitor.c'; then $(CYGPATH_W) 'concurrency/monitor.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/monitor.c'; fi`
 
+concurrency/libcfa_d_a-mutex.o: concurrency/mutex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_d_a-mutex.o -MD -MP -MF concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo -c -o concurrency/libcfa_d_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_d_a-mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_d_a-mutex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_d_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
+
+concurrency/libcfa_d_a-mutex.obj: concurrency/mutex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_d_a-mutex.obj -MD -MP -MF concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo -c -o concurrency/libcfa_d_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_d_a-mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_d_a-mutex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_d_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
+
 libcfa_d_a-assert.o: assert.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT libcfa_d_a-assert.o -MD -MP -MF $(DEPDIR)/libcfa_d_a-assert.Tpo -c -o libcfa_d_a-assert.o `test -f 'assert.c' || echo '$(srcdir)/'`assert.c
@@ -1237,4 +1259,18 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_a-monitor.obj `if test -f 'concurrency/monitor.c'; then $(CYGPATH_W) 'concurrency/monitor.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/monitor.c'; fi`
+
+concurrency/libcfa_a-mutex.o: concurrency/mutex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_a-mutex.o -MD -MP -MF concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo -c -o concurrency/libcfa_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_a-mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_a-mutex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
+
+concurrency/libcfa_a-mutex.obj: concurrency/mutex.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_a-mutex.obj -MD -MP -MF concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo -c -o concurrency/libcfa_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_a-mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_a-mutex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
 
 libcfa_a-assert.o: assert.c
Index: src/libcfa/bits/containers.h
===================================================================
--- src/libcfa/bits/containers.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/bits/containers.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -183,4 +183,9 @@
 		verify( *tail == NULL );
 		return val;
+	}
+
+	forall(dtype T | is_node(T))
+	static inline bool ?!=?( __queue(T) & this, zero_t zero ) {
+		return this.head != 0;
 	}
 #endif
@@ -261,4 +266,9 @@
 		__get( node ).prev = NULL;
 	}
+
+	forall(dtype T | sized(T))
+	static inline bool ?!=?( __dllist(T) & this, zero_t zero ) {
+		return this.head != 0;
+	}
 	#undef next
 	#undef prev
Index: src/libcfa/concurrency/kernel
===================================================================
--- src/libcfa/concurrency/kernel	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/concurrency/kernel	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -23,4 +23,5 @@
 extern "C" {
 #include <pthread.h>
+#include <semaphore.h>
 }
 
@@ -43,15 +44,45 @@
 extern struct cluster * mainCluster;
 
-enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule };
+enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule, Callback };
+
+typedef void (*__finish_callback_fptr_t)(void);
 
 //TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
 struct FinishAction {
 	FinishOpCode action_code;
+	/*
+	// Union of possible actions
+	union {
+		// Option 1 : locks and threads
+		struct {
+			// 1 thread or N thread
+			union {
+				thread_desc * thrd;
+				struct {
+					thread_desc ** thrds;
+					unsigned short thrd_count;
+				};
+			};
+			// 1 lock or N lock
+			union {
+				__spinlock_t * lock;
+				struct {
+					__spinlock_t ** locks;
+					unsigned short lock_count;
+				};
+			};
+		};
+		// Option 2 : action pointer
+		__finish_callback_fptr_t callback;
+	};
+	/*/
 	thread_desc * thrd;
+	thread_desc ** thrds;
+	unsigned short thrd_count;
 	__spinlock_t * lock;
 	__spinlock_t ** locks;
 	unsigned short lock_count;
-	thread_desc ** thrds;
-	unsigned short thrd_count;
+	__finish_callback_fptr_t callback;
+	//*/
 };
 static inline void ?{}(FinishAction & this) {
@@ -101,4 +132,5 @@
 
 	// Idle lock
+	sem_t idleLock;
 
 	// Link lists fields
Index: src/libcfa/concurrency/kernel.c
===================================================================
--- src/libcfa/concurrency/kernel.c	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/concurrency/kernel.c	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -49,5 +49,5 @@
 thread_desc * mainThread;
 
-struct { __dllist_t(cluster    ) list; __spinlock_t lock; } global_clusters;
+struct { __dllist_t(cluster) list; __spinlock_t lock; } global_clusters;
 
 //-----------------------------------------------------------------------------
@@ -143,4 +143,6 @@
 	runner.proc = &this;
 
+	sem_init(&idleLock, 0, 0);
+
 	start( &this );
 }
@@ -156,4 +158,6 @@
 		pthread_join( kernel_thread, NULL );
 	}
+
+	sem_destroy(&idleLock);
 }
 
@@ -257,23 +261,20 @@
 // its final actions must be executed from the kernel
 void finishRunning(processor * this) with( this->finish ) {
-	if( action_code == Release ) {
-		verify( ! kernelTLS.preemption_state.enabled );
+	verify( ! kernelTLS.preemption_state.enabled );
+	choose( action_code ) {
+	case No_Action:
+		break;
+	case Release:
 		unlock( *lock );
-	}
-	else if( action_code == Schedule ) {
+	case Schedule:
 		ScheduleThread( thrd );
-	}
-	else if( action_code == Release_Schedule ) {
-		verify( ! kernelTLS.preemption_state.enabled );
+	case Release_Schedule:
 		unlock( *lock );
 		ScheduleThread( thrd );
-	}
-	else if( action_code == Release_Multi ) {
-		verify( ! kernelTLS.preemption_state.enabled );
+	case Release_Multi:
 		for(int i = 0; i < lock_count; i++) {
 			unlock( *locks[i] );
 		}
-	}
-	else if( action_code == Release_Multi_Schedule ) {
+	case Release_Multi_Schedule:
 		for(int i = 0; i < lock_count; i++) {
 			unlock( *locks[i] );
@@ -282,7 +283,8 @@
 			ScheduleThread( thrds[i] );
 		}
-	}
-	else {
-		assert(action_code == No_Action);
+	case Callback:
+		callback();
+	default:
+		abort("KERNEL ERROR: Unexpected action to run after thread");
 	}
 }
@@ -291,5 +293,6 @@
 // TODO : find some strategy to put cores to sleep after some time
 void spin(processor * this, unsigned int * spin_count) {
-	(*spin_count)++;
+	// (*spin_count)++;
+	halt(this);
 }
 
@@ -396,6 +399,15 @@
 	with( *thrd->curr_cluster ) {
 		lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
+		bool was_empty = !(ready_queue != 0);
 		append( ready_queue, thrd );
 		unlock( ready_queue_lock );
+
+		if( was_empty ) {
+			lock      (proc_list_lock __cfaabi_dbg_ctx2);
+			if(idles) {
+				wake(idles.head);
+			}
+			unlock    (proc_list_lock);
+		}
 	}
 
@@ -497,4 +509,18 @@
 }
 
+void BlockInternal(__finish_callback_fptr_t callback) {
+	disable_interrupts();
+	with( *kernelTLS.this_processor ) {
+		finish.action_code = Callback;
+		finish.callback    = callback;
+	}
+
+	verify( ! kernelTLS.preemption_state.enabled );
+	returnToKernel();
+	verify( ! kernelTLS.preemption_state.enabled );
+
+	enable_interrupts( __cfaabi_dbg_ctx );
+}
+
 // KERNEL ONLY
 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
@@ -627,21 +653,30 @@
 //=============================================================================================
 
-// void halt(processor * this) with( this ) {
-// 	pthread_mutex_lock( &idle.lock );
-
-
-
-// 	// SKULLDUGGERY: Even if spurious wake-up is a thing
-// 	// spuriously waking up a kernel thread is not a big deal
-// 	// if it is very rare.
-// 	pthread_cond_wait( &idle.cond, &idle.lock);
-// 	pthread_mutex_unlock( &idle.lock );
-// }
-
-// void wake(processor * this) with( this ) {
-// 	pthread_mutex_lock  (&idle.lock);
-// 	pthread_cond_signal (&idle.cond);
-// 	pthread_mutex_unlock(&idle.lock);
-// }
+void halt(processor * this) with( *this ) {
+	with( *cltr ) {
+		lock      (proc_list_lock __cfaabi_dbg_ctx2);
+		remove    (procs, *this);
+		push_front(idles, *this);
+		unlock    (proc_list_lock);
+	}
+
+	__cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this);
+
+	sem_wait(&idleLock);
+
+	__cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this);
+
+	with( *cltr ) {
+		lock      (proc_list_lock __cfaabi_dbg_ctx2);
+		remove    (idles, *this);
+		push_front(procs, *this);
+		unlock    (proc_list_lock);
+	}
+}
+
+void wake(processor * this) {
+	__cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
+	sem_post(&this->idleLock);
+}
 
 //=============================================================================================
Index: src/libcfa/concurrency/kernel_private.h
===================================================================
--- src/libcfa/concurrency/kernel_private.h	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/concurrency/kernel_private.h	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -48,4 +48,5 @@
 void BlockInternal(__spinlock_t * locks [], unsigned short count);
 void BlockInternal(__spinlock_t * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);
+void BlockInternal(__finish_callback_fptr_t callback);
 void LeaveThread(__spinlock_t * lock, thread_desc * thrd);
 
@@ -56,4 +57,6 @@
 void runThread(processor * this, thread_desc * dst);
 void finishRunning(processor * this);
+void halt(processor * this);
+void wake(processor * this);
 void terminate(processor * this);
 void spin(processor * this, unsigned int * spin_count);
Index: src/libcfa/concurrency/monitor.c
===================================================================
--- src/libcfa/concurrency/monitor.c	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/concurrency/monitor.c	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -297,5 +297,5 @@
 	this.count = count;
 
-	// Sort monitors based on address -> TODO use a sort specialized for small numbers
+	// Sort monitors based on address
 	__libcfa_small_sort(this.m, count);
 
Index: src/libcfa/concurrency/mutex
===================================================================
--- src/libcfa/concurrency/mutex	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
+++ src/libcfa/concurrency/mutex	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -0,0 +1,171 @@
+
+//                              -*- Mode: CFA -*-
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// mutex --
+//
+// Author           : Thierry Delisle
+// Created On       : Fri May 25 01:24:09 2018
+// Last Modified By : Thierry Delisle
+// Last Modified On : Fri May 25 01:24:12 2018
+// Update Count     : 0
+//
+
+#pragma once
+
+#include <stdbool.h>
+
+#include "bits/algorithms.h"
+#include "bits/locks.h"
+
+#include "invoke.h"
+#include "time_t.h"
+
+//-----------------------------------------------------------------------------
+// Locks
+
+// Exclusive lock - non-recursive
+// ---
+struct mutex_lock {
+	// Spin lock used for mutual exclusion
+	__spinlock_t lock;
+
+	// List of blocked threads
+	__queue_t(struct thread_desc) blocked_threads;
+
+	// Locked flag
+	bool is_locked;
+};
+
+void ?{}(mutex_lock & this);
+void ^?{}(mutex_lock & this);
+void lock(mutex_lock & this);
+bool try_lock(mutex_lock & this);
+void unlock(mutex_lock & this);
+
+// Exclusive lock - recursive
+// ---
+struct recursive_mutex_lock{
+	// Spin lock used for mutual exclusion
+	__spinlock_t lock;
+
+	// List of blocked threads
+	__queue_t(struct thread_desc) blocked_threads;
+
+	// Current thread owning the lock
+	struct thread_desc * owner;
+
+	// Number of recursion level
+	size_t recursion_count;
+};
+
+void ?{}(recursive_mutex_lock & this);
+void ^?{}(recursive_mutex_lock & this);
+void lock(recursive_mutex_lock & this);
+bool try_lock(recursive_mutex_lock & this);
+void unlock(recursive_mutex_lock & this);
+
+trait is_lock(dtype L | sized(L)) {
+	void lock  (L &);
+	void unlock(L &);
+};
+
+//-----------------------------------------------------------------------------
+// Condition variables
+
+struct condition_variable {
+	// Spin lock used for mutual exclusion
+	__spinlock_t lock;
+
+	// List of blocked threads
+	__queue_t(struct thread_desc) blocked_threads;
+};
+
+void ?{}(condition_variable & this);
+void ^?{}(condition_variable & this);
+
+void notify_one(condition_variable & this);
+void notify_all(condition_variable & this);
+
+void wait(condition_variable & this);
+
+forall(dtype L | is_lock(L))
+void wait(condition_variable & this, L & l);
+
+//-----------------------------------------------------------------------------
+// Scopes
+forall(dtype L | is_lock(L)) {
+	#if !defined( __TUPLE_ARRAYS_EXIST__ )
+	void lock  ( L * locks [], size_t count);
+	void unlock( L * locks [], size_t count);
+
+	struct lock_scope {
+		L **   locks;
+		size_t count;
+	};
+
+	static inline void ?{}(lock_scope(L) & this) {
+		this.locks = NULL;
+		this.count = 0;
+	}
+
+	static inline void ^?{}(lock_scope(L) & this) {
+		if(this.count > 0) {
+			unlock(this.locks, this.count);
+		}
+	}
+
+	static inline lock_scope(L) lock( L * locks [], size_t count, lock_scope(L) & scope) {
+		lock(locks, count);
+		scope.locks = locks;
+		scope.count = count;
+	}
+
+	static inline void unlock( lock_scope(L) & this ) {
+		unlock(this.locks, this.count);
+		this.count = 0;
+	}
+
+	static inline void release( lock_scope(L) & this ) {
+		this.count = 0;
+	}
+	#else
+	void lock( [L &...] locks );
+	void unlock( [L &...] locks );
+
+	forall(size_t N)
+	struct lock_scope {
+		bool released;
+		[L &... N] locks;
+	};
+
+	void ?{}(lock_scope(L) & this) = void;
+	void ?{}(lock_scope(L) & this, lock_scope(L) other) = void;
+	void ?move?(lock_scope(L) & this, lock_scope(L) & other) = default;
+
+	static inline void ^?{}(lock_scope(L) & this) {
+		if( !this.released ) {
+			unlock(this.locks);
+		}
+	}
+
+	forall(size_t N)
+	static inline lock_scope(L, N) lock( [L &...] locks ) {
+		lock(locks);
+		return @{false, locks};
+	}
+
+	static inline void unlock( lock_scope(L) & this ) {
+		unlock(this.locks);
+		this.released = true
+	}
+
+	static inline void release( lock_scope(L) & this ) {
+		this.released = true;
+	}
+	#endif
+}
Index: src/libcfa/concurrency/mutex.c
===================================================================
--- src/libcfa/concurrency/mutex.c	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
+++ src/libcfa/concurrency/mutex.c	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -0,0 +1,193 @@
+
+//                              -*- Mode: CFA -*-
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// mutex.c --
+//
+// Author           : Thierry Delisle
+// Created On       : Fri May 25 01:37:11 2018
+// Last Modified By : Thierry Delisle
+// Last Modified On : Fri May 25 01:37:51 2018
+// Update Count     : 0
+//
+
+#include "mutex"
+
+#include "kernel_private.h"
+
+//-----------------------------------------------------------------------------
+// Locks
+
+// Exclusive lock - non-recursive
+// ---
+void ?{}(mutex_lock & this) {
+	this.lock{};
+	this.blocked_threads{};
+}
+
+void ^?{}(mutex_lock & this) {
+	// default
+}
+
+void lock(mutex_lock & this) with(this) {
+	lock( lock __cfaabi_dbg_ctx2 );
+	if( is_locked ) {
+		append( blocked_threads, kernelTLS.this_thread );
+		BlockInternal( &lock );
+	}
+	else {
+		is_locked = true;
+		unlock( lock );
+	}
+}
+
+bool try_lock(mutex_lock & this) with(this) {
+	bool ret = false;
+	lock( lock __cfaabi_dbg_ctx2 );
+	if( !is_locked ) {
+		ret = true;
+		is_locked = true;
+	}
+	unlock( lock );
+	return ret;
+}
+
+void unlock(mutex_lock & this) {
+	lock( this.lock __cfaabi_dbg_ctx2 );
+	this.is_locked = (this.blocked_threads != 0);
+	WakeThread(
+		pop_head( this.blocked_threads )
+	);
+	unlock( this.lock );
+}
+
+// Exclusive lock - non-recursive
+// ---
+void ?{}(recursive_mutex_lock & this) {
+	this.lock{};
+	this.blocked_threads{};
+	this.owner = NULL;
+	this.recursion_count = 0;
+}
+
+void ^?{}(recursive_mutex_lock & this) {
+	// default
+}
+
+void lock(recursive_mutex_lock & this) with(this) {
+	lock( lock __cfaabi_dbg_ctx2 );
+	if( owner == NULL ) {
+		owner = kernelTLS.this_thread;
+		recursion_count = 1;
+		unlock( lock );
+	}
+	else if( owner == kernelTLS.this_thread ) {
+		recursion_count++;
+		unlock( lock );
+	}
+	else {
+		append( blocked_threads, kernelTLS.this_thread );
+		BlockInternal( &lock );
+	}
+}
+
+bool try_lock(recursive_mutex_lock & this) with(this) {
+	bool ret = false;
+	lock( lock __cfaabi_dbg_ctx2 );
+	if( owner == NULL ) {
+		owner = kernelTLS.this_thread;
+		recursion_count = 1;
+		ret = true;
+	}
+	else if( owner == kernelTLS.this_thread ) {
+		recursion_count++;
+		ret = true;
+	}
+	unlock( lock );
+	return ret;
+}
+
+void unlock(recursive_mutex_lock & this) with(this) {
+	lock( lock __cfaabi_dbg_ctx2 );
+	recursion_count--;
+	if( recursion_count == 0 ) {
+		thread_desc * thrd = pop_head( blocked_threads );
+		owner = thrd;
+		recursion_count = (thrd ? 1 : 0);
+		WakeThread( thrd );
+	}
+	unlock( lock );
+}
+
+//-----------------------------------------------------------------------------
+// Conditions
+void ?{}(condition_variable & this) {
+	this.blocked_threads{};
+}
+
+void ^?{}(condition_variable & this) {
+	// default
+}
+
+void notify_one(condition_variable & this) with(this) {
+	lock( lock __cfaabi_dbg_ctx2 );
+	WakeThread(
+		pop_head( this.blocked_threads )
+	);
+	unlock( lock );
+}
+
+void notify_all(condition_variable & this) with(this) {
+	lock( lock __cfaabi_dbg_ctx2 );
+	while(this.blocked_threads) {
+		WakeThread(
+			pop_head( this.blocked_threads )
+		);
+	}
+	unlock( lock );
+}
+
+void wait(condition_variable & this) {
+	lock( this.lock __cfaabi_dbg_ctx2 );
+	append( this.blocked_threads, kernelTLS.this_thread );
+	BlockInternal( &this.lock );
+}
+
+forall(dtype L | is_lock(L))
+void wait(condition_variable & this, L & l) {
+	lock( this.lock __cfaabi_dbg_ctx2 );
+	append( this.blocked_threads, kernelTLS.this_thread );
+	void __unlock(void) {
+		unlock(l);
+		unlock(this.lock);
+	}
+	BlockInternal( __unlock );
+	lock(l);
+}
+
+//-----------------------------------------------------------------------------
+// Scopes
+forall(dtype L | is_lock(L))
+void lock_all  ( L * locks[], size_t count) {
+	// Sort locks based on addresses
+	__libcfa_small_sort(locks, count);
+
+	// Lock all
+	for(size_t i = 0; i < count; i++) {
+		L * l = locks[i];
+		lock( *l );
+	}
+}
+
+forall(dtype L | is_lock(L))
+void unlock_all( L * locks[], size_t count) {
+	// Lock all
+	for(size_t i = 0; i < count; i++) {
+		L * l = locks[i];
+		unlock( *l );
+	}
+}
Index: src/libcfa/concurrency/preemption.c
===================================================================
--- src/libcfa/concurrency/preemption.c	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/libcfa/concurrency/preemption.c	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -266,4 +266,5 @@
 void terminate(processor * this) {
 	this->do_terminate = true;
+	wake(this);
 	sigval_t value = { PREEMPT_TERMINATE };
 	pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
Index: src/tests/concurrent/signal/barge.c
===================================================================
--- src/tests/concurrent/signal/barge.c	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ 	(revision )
@@ -1,117 +1,0 @@
-//----------------------------------------------------------------------------------------
-//----------------------------------------------------------------------------------------
-//
-//		DEPRECATED TEST
-//
-//----------------------------------------------------------------------------------------
-//----------------------------------------------------------------------------------------
-
-#include <fstream>
-#include <kernel>
-#include <monitor>
-#include <stdlib>
-#include <thread>
-
-static const unsigned long N = 50_000ul;
-
-#ifndef PREEMPTION_RATE
-#define PREEMPTION_RATE 10`ms
-#endif
-
-Duration default_preemption() {
-	return 0;
-}
-enum state_t { WAIT, SIGNAL, BARGE };
-
-monitor global_t {};
-
-monitor global_data_t {
-	volatile bool done;
-	int counter;
-	state_t state;
-
-	unsigned short do_signal;
-	unsigned short do_wait2;
-	unsigned short do_wait1;
-};
-
-void ?{} ( global_data_t & this ) {
-	this.done = false;
-	this.counter = 0;
-	this.state = BARGE;
-
-	this.do_signal = 6;
-	this.do_wait1  = 1;
-	this.do_wait2  = 3;
-}
-
-void ^?{} ( global_data_t & this ) {}
-
-global_t globalA;
-global_t globalB;
-global_data_t globalC;
-
-condition cond;
-
-thread Threads {};
-
-bool logicC( global_t & mutex a, global_t & mutex b, global_data_t & mutex c ) {
-	c.counter++;
-
-	if( (c.counter % 1000) == 0 ) sout | c.counter | endl;
-
-	int action = c.counter % 10;
-
-	if( action == 0 ) {
-		c.do_signal = max( random( 10 ), 1);
-		c.do_wait1 = random( c.do_signal );
-		c.do_wait2 = random( c.do_signal );
-
-		if(c.do_wait1 == c.do_wait2) sout | "Same" | endl;
-	}
-
-	if( action == c.do_wait1 || action == c.do_wait2 ) {
-		c.state = WAIT;
-		wait( cond );
-
-		if(c.state != SIGNAL) {
-			sout | "ERROR Barging detected" | c.counter | endl;
-			abort();
-		}
-	}
-	else if( action == c.do_signal ) {
-		c.state = SIGNAL;
-
-		signal( cond );
-		signal( cond );
-	}
-	else {
-		c.state = BARGE;
-	}
-
-	if( c.counter >= N ) c.done = true;
-	return !c.done;
-}
-
-bool logicB( global_t & mutex a, global_t & mutex b ) {
-	return logicC(a, b, globalC);
-}
-
-bool logicA( global_t & mutex a ) {
-	return logicB(a, globalB);
-}
-
-void main( Threads & this ) {
-	while( logicA(globalA) ) { yield(); };
-}
-
-static thread_desc * volatile the_threads;
-
-int main(int argc, char* argv[]) {
-	srandom(0);
-	processor p;
-	{
-		Threads t[17];
-		the_threads = (thread_desc*)t;
-	}
-}
Index: src/tests/concurrent/signal/block.c
===================================================================
--- src/tests/concurrent/signal/block.c	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/tests/concurrent/signal/block.c	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -40,5 +40,5 @@
 }
 
-void ^?{} ( global_data_t & this ) {}
+void ^?{} ( global_data_t & mutex this ) {}
 
 global_data_t globalA, globalB;
Index: src/tests/concurrent/signal/disjoint.c
===================================================================
--- src/tests/concurrent/signal/disjoint.c	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/tests/concurrent/signal/disjoint.c	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -26,5 +26,5 @@
 monitor global_data_t;
 void ?{}( global_data_t & this );
-void ^?{} ( global_data_t & this );
+void ^?{} ( global_data_t & mutex this );
 
 monitor global_data_t {
@@ -42,5 +42,5 @@
 }
 
-void ^?{} ( global_data_t & this ) {}
+void ^?{} ( global_data_t & mutex this ) {}
 
 //------------------------------------------------------------------------------
Index: src/tests/pybin/tools.py
===================================================================
--- src/tests/pybin/tools.py	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/tests/pybin/tools.py	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -83,4 +83,20 @@
 	return sh(cmd)
 
+def which(program):
+    import os
+    def is_exe(fpath):
+        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+    fpath, fname = os.path.split(program)
+    if fpath:
+        if is_exe(program):
+            return program
+    else:
+        for path in os.environ["PATH"].split(os.pathsep):
+            exe_file = os.path.join(path, program)
+            if is_exe(exe_file):
+                return exe_file
+
+    return None
 ################################################################################
 #               file handling
@@ -219,4 +235,13 @@
 	return False
 
+def fancy_print(text):
+	column = which('column')
+	if column:
+		cmd = "%s 2> /dev/null" % column
+		print(cmd)
+		proc = Popen(cmd, stdin=PIPE, stderr=None, shell=True)
+		proc.communicate(input=text)
+	else:
+		print(text)
 
 settings.set_machine_default( getMachineType )
Index: src/tests/test.py
===================================================================
--- src/tests/test.py	(revision 35718a956595deb97b970ddc59681cb3586e8fcc)
+++ src/tests/test.py	(revision 94b1022a3fd279df5304e58231633a956e3fb672)
@@ -277,5 +277,5 @@
 	elif options.list :
 		print("Listing for %s:%s"% (settings.arch.string, settings.debug.string))
-		print("\n".join(map(lambda t: "%s" % (t.toString()), tests)))
+		fancy_print("\n".join(map(lambda t: "%s" % (t.toString()), tests)))
 
 	else :
