Index: src/libcfa/concurrency/coroutine
===================================================================
--- src/libcfa/concurrency/coroutine	(revision 60c3b06cd0b60317c7cc378a11ae1505498f55de)
+++ src/libcfa/concurrency/coroutine	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
@@ -103,4 +103,5 @@
 		// set last resumer
 		dst->last = src;
+		dst->starter = dst->starter ? dst->starter : src;
 	} // if
 
Index: src/libcfa/concurrency/coroutine.c
===================================================================
--- src/libcfa/concurrency/coroutine.c	(revision 60c3b06cd0b60317c7cc378a11ae1505498f55de)
+++ src/libcfa/concurrency/coroutine.c	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
@@ -65,5 +65,5 @@
 	this.errno_ = 0;
 	this.state = Start;
-	this.starter = this_coroutine;
+	this.starter = NULL;
 	this.last = NULL;
 }
@@ -176,9 +176,9 @@
 
 		assertf( src->starter != 0,
-			"Attempt to suspend coroutine \"%.256s\" (%p) that does not have a starter.\n"
-			"Possible cause is a resume of a coroutine already destroyed or not yet constructed",
+			"Attempt to suspend/leave coroutine \"%.256s\" (%p) that has never been resumed.\n"
+			"Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
 			src->name, src );
 		assertf( src->starter->state != Halted,
-			"Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"
+			"Attempt by coroutine \"%.256s\" (%p) to suspend/leave back to terminated coroutine \"%.256s\" (%p).\n"
 			"Possible cause is terminated coroutine's main routine has already returned.",
 			src->name, src, src->starter->name, src->starter );
Index: src/libcfa/concurrency/kernel.c
===================================================================
--- src/libcfa/concurrency/kernel.c	(revision 60c3b06cd0b60317c7cc378a11ae1505498f55de)
+++ src/libcfa/concurrency/kernel.c	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
@@ -115,5 +115,5 @@
 void ?{}(processorCtx_t & this, processor * proc) {
 	(this.__cor){ "Processor" };
-	this.__cor.starter = &mainThread->cor;
+	this.__cor.starter = NULL;
 	this.proc = proc;
 	proc->runner = &this;
Index: src/tests/.expect/pingpong.txt
===================================================================
--- src/tests/.expect/pingpong.txt	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
+++ src/tests/.expect/pingpong.txt	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
@@ -0,0 +1,40 @@
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
+ping
+pong
Index: src/tests/.expect/prodcons.txt
===================================================================
--- src/tests/.expect/prodcons.txt	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
+++ src/tests/.expect/prodcons.txt	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
@@ -0,0 +1,33 @@
+47 88
+47 88
+ $1
+ $1
+1
+68 24
+ # 1
+68 24
+ $2
+ $2
+2
+58 18
+ # 2
+58 18
+ $3
+ $3
+3
+55 82
+ # 3
+55 82
+ $4
+ $4
+4
+60 87
+ # 4
+60 87
+ $5
+ $5
+5
+ # 5
+cons stops
+prod stops
+main stops
Index: src/tests/pingpong.c
===================================================================
--- src/tests/pingpong.c	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
+++ src/tests/pingpong.c	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
@@ -0,0 +1,55 @@
+// 
+// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+// 
+// pingpong.c -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Wed Sep 20 11:55:23 2017
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Sep 20 13:41:39 2017
+// Update Count     : 26
+// 
+
+#include <coroutine>
+#include <fstream>
+
+coroutine PingPong {
+	const char * name;
+	/* const */ unsigned int N;
+	PingPong * part;
+};
+
+void ?{}( PingPong & this, const char * name, unsigned int N, PingPong & part ) {
+	this.name = name;
+	this.N = N;
+	this.part = &part;
+}
+void ?{}( PingPong & this, const char * name, unsigned int N ) {
+	this{ name, N, *(PingPong *)0 };
+}
+void cycle( PingPong & pingpong ) {
+	resume( pingpong );
+}
+void partner( PingPong & this, PingPong & part ) {
+	this.part = &part;
+	resume( this );
+}
+void main( PingPong & pingpong ) {						// ping's starter ::main, pong's starter ping
+	for ( unsigned int i = 0; i < pingpong.N; i += 1 ) {
+		sout | pingpong.name | endl;
+		cycle( *pingpong.part );
+	} // for
+}
+int main() {
+	enum { N = 20 };
+	PingPong ping = { "ping", N }, pong = { "pong", N, ping };
+	partner( ping, pong );
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "cfa pingpong.c" //
+// End: //
Index: src/tests/prodcons.c
===================================================================
--- src/tests/prodcons.c	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
+++ src/tests/prodcons.c	(revision 175522617a3360c31438f0b5c6ae6d0ccd67970d)
@@ -0,0 +1,100 @@
+// 
+// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+// 
+// prodcons.c -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Mon Sep 18 12:23:39 2017
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Sep 20 17:03:28 2017
+// Update Count     : 40
+// 
+
+#include <fstream>
+#include <coroutine>
+#include <stdlib>										// rand48
+#include <unistd.h>										// getpid
+
+coroutine Cons;											// forward
+int delivery( Cons & cons, int p1, int p2 );
+void stop( Cons & cons );
+
+coroutine Prod {
+	Cons *c;
+	int N, money, receipt;
+};
+void main( Prod & prod ) {								// starter ::main
+	// 1st resume starts here
+	for ( int i = 0; i < prod.N; i += 1 ) {
+		int p1 = (unsigned int)rand48() % 100;			// non-negative
+		int p2 = (unsigned int)rand48() % 100;
+		sout | p1 | " " | p2 | endl;
+		int status = delivery( *prod.c, p1, p2 );
+		sout | " $" | prod.money | endl;
+		sout | status | endl;
+		prod.receipt += 1;
+	}
+	stop( *prod.c );
+	sout | "prod stops" | endl;
+}
+int payment( Prod & prod, int money ) {
+	prod.money = money;
+	resume( prod );										// main 1st time, then
+	return prod.receipt;								// prod in delivery
+}
+void start( Prod & prod, int N, Cons &c ) {
+	prod.N = N;
+	prod.c = &c;
+	prod.receipt = 0;
+	resume( prod );										// activate main
+}
+
+coroutine Cons {
+	Prod * p;
+	int p1, p2, status;
+	bool done;
+};
+void ?{}( Cons & cons, Prod & p ) {
+	cons.p = &p;
+	cons.status = 0;
+	cons.done = false;
+}
+void ^?{}( Cons & cons ) {}
+void main( Cons & cons ) {								// starter prod
+	// 1st resume starts here
+	int money = 1, receipt;
+	for ( ; ! cons.done; ) {
+		sout | cons.p1 | " " | cons.p2 | endl;
+		sout | " $" | money | endl;
+		cons.status += 1;
+		receipt = payment( *cons.p, money );
+		sout | " #" | receipt | endl;
+		money += 1;
+	}
+	sout | "cons stops" | endl;
+}
+int delivery( Cons & cons, int p1, int p2 ) {
+	cons.p1 = p1;
+	cons.p2 = p2;
+	resume( cons );										// main 1st time, then
+	return cons.status;									// cons in payment
+}
+void stop( Cons & cons ) {
+	cons.done = true;
+	resume( cons );										// activate payment
+}
+int main() {
+	Prod prod;
+	Cons cons = { prod };
+	rand48seed( /* getpid() */ 103 );					// fixed seed for testing
+	start( prod, 5, cons );
+	sout | "main stops" | endl;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "cfa prodcons.c" //
+// End: //
