Index: libcfa/src/concurrency/coroutine.cfa
===================================================================
--- libcfa/src/concurrency/coroutine.cfa	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/concurrency/coroutine.cfa	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -215,4 +215,8 @@
 		return cor;
 	}
+
+	struct $coroutine * __cfactx_cor_active(void) {
+		return active_coroutine();
+	}
 }
 
Index: libcfa/src/concurrency/invoke.c
===================================================================
--- libcfa/src/concurrency/invoke.c	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/concurrency/invoke.c	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -29,4 +29,5 @@
 // Called from the kernel when starting a coroutine or task so must switch back to user mode.
 
+extern struct $coroutine * __cfactx_cor_active(void);
 extern struct $coroutine * __cfactx_cor_finish(void);
 extern void __cfactx_cor_leave ( struct $coroutine * );
@@ -35,4 +36,8 @@
 extern void disable_interrupts() OPTIONAL_THREAD;
 extern void enable_interrupts( __cfaabi_dbg_ctx_param );
+
+struct exception_context_t * this_exception_context() {
+	return &__get_stack( __cfactx_cor_active() )->exception_context;
+}
 
 void __cfactx_invoke_coroutine(
Index: libcfa/src/concurrency/invoke.h
===================================================================
--- libcfa/src/concurrency/invoke.h	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/concurrency/invoke.h	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -98,4 +98,6 @@
 	}
 
+	struct exception_context_t * this_exception_context();
+
 	// struct which calls the monitor is accepting
 	struct __waitfor_mask_t {
Index: libcfa/src/concurrency/io.cfa
===================================================================
--- libcfa/src/concurrency/io.cfa	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/concurrency/io.cfa	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -359,12 +359,12 @@
 
 			// We got the lock
+			// Collect the submissions
 			unsigned to_submit = __collect_submitions( ring );
+
+			// Actually submit
 			int ret = __io_uring_enter( ring, to_submit, false );
-			if( ret < 0 ) {
-				unlock(ring.submit_q.lock);
-				return;
-			}
-
-			/* paranoid */ verify( ret > 0 || to_submit == 0 || (ring.ring_flags & IORING_SETUP_SQPOLL) );
+
+			unlock(ring.submit_q.lock);
+			if( ret < 0 ) return;
 
 			// Release the consumed SQEs
@@ -372,11 +372,9 @@
 
 			// update statistics
-			__STATS__( true,
+			__STATS__( false,
 				io.submit_q.submit_avg.rdy += to_submit;
 				io.submit_q.submit_avg.csm += ret;
 				io.submit_q.submit_avg.cnt += 1;
 			)
-
-			unlock(ring.submit_q.lock);
 		}
 		else {
Index: libcfa/src/concurrency/io/setup.cfa
===================================================================
--- libcfa/src/concurrency/io/setup.cfa	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/concurrency/io/setup.cfa	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -298,5 +298,11 @@
 		if( params_in.poll_complete ) params.flags |= IORING_SETUP_IOPOLL;
 
-		uint32_t nentries = params_in.num_entries;
+		uint32_t nentries = params_in.num_entries != 0 ? params_in.num_entries : 256;
+		if( !is_pow2(nentries) ) {
+			abort("ERROR: I/O setup 'num_entries' must be a power of 2\n");
+		}
+		if( params_in.poller_submits && params_in.eager_submits ) {
+			abort("ERROR: I/O setup 'poller_submits' and 'eager_submits' cannot be used together\n");
+		}
 
 		int fd = syscall(__NR_io_uring_setup, nentries, &params );
Index: libcfa/src/concurrency/iocall.cfa
===================================================================
--- libcfa/src/concurrency/iocall.cfa	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/concurrency/iocall.cfa	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -101,5 +101,4 @@
 	#endif
 
-
 	#define __submit_prelude \
 		if( 0 != (submit_flags & LINK_FLAGS) ) { errno = ENOTSUP; return -1; } \
@@ -110,6 +109,7 @@
 		struct io_uring_sqe * sqe; \
 		uint32_t idx; \
+		uint8_t sflags = REGULAR_FLAGS & submit_flags; \
 		[sqe, idx] = __submit_alloc( ring, (uint64_t)(uintptr_t)&data ); \
-		sqe->flags = REGULAR_FLAGS & submit_flags;
+		sqe->flags = sflags;
 
 	#define __submit_wait \
@@ -186,5 +186,12 @@
 			__submit_prelude
 
-			(*sqe){ IORING_OP_READV, fd, iov, iovcnt, offset };
+			sqe->opcode = IORING_OP_READV;
+			sqe->ioprio = 0;
+			sqe->fd = fd;
+			sqe->off = offset;
+			sqe->addr = (uint64_t)(uintptr_t)iov;
+			sqe->len = iovcnt;
+			sqe->rw_flags = 0;
+			sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0;
 
 			__submit_wait
Index: libcfa/src/exception.c
===================================================================
--- libcfa/src/exception.c	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/exception.c	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -59,11 +59,9 @@
 
 
-// Temperary global exception context. Does not work with concurency.
-static struct exception_context_t shared_stack = {NULL, NULL};
-
 // Get the current exception context.
 // There can be a single global until multithreading occurs, then each stack
-// needs its own. It will have to be updated to handle that.
-struct exception_context_t * this_exception_context() {
+// needs its own. We get this from libcfathreads (no weak attribute).
+__attribute__((weak)) struct exception_context_t * this_exception_context() {
+	static struct exception_context_t shared_stack = {NULL, NULL};
 	return &shared_stack;
 }
Index: libcfa/src/parseargs.cfa
===================================================================
--- libcfa/src/parseargs.cfa	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/parseargs.cfa	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -19,4 +19,5 @@
 	extern          long long int strtoll (const char* str, char** endptr, int base);
 	extern unsigned long long int strtoull(const char* str, char** endptr, int base);
+	extern                 double strtod  (const char* str, char** endptr);
 }
 
@@ -28,15 +29,5 @@
 extern char ** cfa_args_envp;
 
-void printopt(FILE * out, int width, int max, char sn, const char * ln, const char * help) {
-	int hwidth = max - (11 + width);
-	if(hwidth <= 0) hwidth = max;
-
-	fprintf(out, "  -%c, --%-*s   %.*s\n", sn, width, ln, hwidth, help);
-	for() {
-		help += min(strlen(help), hwidth);
-		if('\0' == *help) break;
-		fprintf(out, "%*s%.*s\n", width + 11, "", hwidth, help);
-	}
-}
+static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out)  __attribute__ ((noreturn));
 
 void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) {
@@ -44,4 +35,6 @@
 }
 
+//-----------------------------------------------------------------------------
+// getopt_long wrapping
 void parse_args(
 	int argc,
@@ -53,6 +46,4 @@
 ) {
 	struct option optarr[opt_count + 2];
-	int width = 0;
-	int max_width = 1_000_000;
 	{
 		int idx = 0;
@@ -69,7 +60,4 @@
 				}
 				idx++;
-
-				int w = strlen(options[i].long_name);
-				if(w > width) width = w;
 			}
 		}
@@ -106,5 +94,5 @@
 				out = stdout;
 			case '?':
-				goto USAGE;
+				usage(argv[0], options, opt_count, usage, out);
 			default:
 				for(i; opt_count) {
@@ -115,5 +103,5 @@
 
 						fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
-						goto USAGE;
+						usage(argv[0], options, opt_count, usage, out);
 					}
 				}
@@ -122,6 +110,41 @@
 
 	}
-
-	USAGE:;
+}
+
+//-----------------------------------------------------------------------------
+// Print usage
+static void printopt(FILE * out, int width, int max, char sn, const char * ln, const char * help) {
+	int hwidth = max - (11 + width);
+	if(hwidth <= 0) hwidth = max;
+
+	fprintf(out, "  -%c, --%-*s   %.*s\n", sn, width, ln, hwidth, help);
+	for() {
+		help += min(strlen(help), hwidth);
+		if('\0' == *help) break;
+		fprintf(out, "%*s%.*s\n", width + 11, "", hwidth, help);
+	}
+}
+
+void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
+	usage(cfa_args_argv[0], options, opt_count, usage, error ? stderr : stdout);
+}
+
+void print_args_usage(int , char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
+	usage(argv[0], options, opt_count, usage, error ? stderr : stdout);
+}
+
+static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * help, FILE * out) __attribute__((noreturn)) {
+	int width = 0;
+	{
+		int idx = 0;
+		for(i; opt_count) {
+			if(options[i].long_name) {
+				int w = strlen(options[i].long_name);
+				if(w > width) width = w;
+			}
+		}
+	}
+
+	int max_width = 1_000_000;
 	int outfd = fileno(out);
 	if(isatty(outfd)) {
@@ -132,5 +155,5 @@
 	}
 
-	fprintf(out, "Usage:\n  %s %s\n", argv[0], usage);
+	fprintf(out, "Usage:\n  %s %s\n", cmd, help);
 
 	for(i; opt_count) {
@@ -141,4 +164,6 @@
 }
 
+//-----------------------------------------------------------------------------
+// Typed argument parsing
 bool parse_yesno(const char * arg, bool & value ) {
 	if(strcmp(arg, "yes") == 0) {
@@ -167,4 +192,13 @@
 bool parse(const char * arg, const char * & value ) {
 	value = arg;
+	return true;
+}
+
+bool parse(const char * arg, int & value) {
+	char * end;
+	int r = strtoll(arg, &end, 10);
+	if(*end != '\0') return false;
+
+	value = r;
 	return true;
 }
@@ -200,10 +234,10 @@
 }
 
-bool parse(const char * arg, int & value) {
-	char * end;
-	int r = strtoll(arg, &end, 10);
-	if(*end != '\0') return false;
-
-	value = r;
-	return true;
-}
+bool parse(const char * arg, double & value) {
+	char * end;
+	double r = strtod(arg, &end);
+	if(*end != '\0') return false;
+
+	value = r;
+	return true;
+}
Index: libcfa/src/parseargs.hfa
===================================================================
--- libcfa/src/parseargs.hfa	(revision 68d40b7eea06552e21a22782971e7c20ac6492cc)
+++ libcfa/src/parseargs.hfa	(revision 36de20dddab02da043205d974d1cbd6d176f5605)
@@ -34,4 +34,7 @@
 void parse_args( int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, char ** & left );
 
+void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn));
+void print_args_usage(int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn));
+
 bool parse_yesno   (const char *, bool & );
 bool parse_settrue (const char *, bool & );
@@ -39,6 +42,7 @@
 
 bool parse(const char *, const char * & );
+bool parse(const char *, int & );
 bool parse(const char *, unsigned & );
 bool parse(const char *, unsigned long & );
 bool parse(const char *, unsigned long long & );
-bool parse(const char *, int & );
+bool parse(const char *, double & );
