Index: libcfa/src/concurrency/io.cfa
===================================================================
--- libcfa/src/concurrency/io.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/io.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -133,5 +133,5 @@
 	}
 
-	void __cfa_io_flush( processor * proc ) {
+	bool __cfa_io_flush( processor * proc, bool wait ) {
 		/* paranoid */ verify( ! __preemption_enabled() );
 		/* paranoid */ verify( proc );
@@ -141,13 +141,8 @@
 		$io_context & ctx = *proc->io.ctx;
 
-		// for(i; 2) {
-		// 	unsigned idx = proc->rdq.id + i;
-		// 	cltr->ready_queue.lanes.tscs[idx].tv = -1ull;
-		// }
-
 		__ioarbiter_flush( ctx );
 
 		__STATS__( true, io.calls.flush++; )
-		int ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, 0, 0, (sigset_t *)0p, _NSIG / 8);
+		int ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, wait ? 1 : 0, 0, (sigset_t *)0p, _NSIG / 8);
 		if( ret < 0 ) {
 			switch((int)errno) {
@@ -157,9 +152,5 @@
 				// Update statistics
 				__STATS__( false, io.calls.errors.busy ++; )
-				// for(i; 2) {
-				// 	unsigned idx = proc->rdq.id + i;
-				// 	cltr->ready_queue.lanes.tscs[idx].tv = rdtscl();
-				// }
-				return;
+				return false;
 			default:
 				abort( "KERNEL ERROR: IO_URING SYSCALL - (%d) %s\n", (int)errno, strerror(errno) );
@@ -182,12 +173,8 @@
 
 		ctx.proc->io.pending = false;
-
 		ready_schedule_lock();
-		__cfa_io_drain( proc );
+		bool ret = __cfa_io_drain( proc );
 		ready_schedule_unlock();
-		// for(i; 2) {
-		// 	unsigned idx = proc->rdq.id + i;
-		// 	cltr->ready_queue.lanes.tscs[idx].tv = rdtscl();
-		// }
+		return ret;
 	}
 
@@ -293,5 +280,4 @@
 	}
 
-
 	//=============================================================================================
 	// submission
@@ -311,10 +297,10 @@
 		// Make the sqes visible to the submitter
 		__atomic_store_n(sq.kring.tail, tail + have, __ATOMIC_RELEASE);
-		sq.to_submit++;
+		sq.to_submit += have;
 
 		ctx->proc->io.pending = true;
 		ctx->proc->io.dirty   = true;
 		if(sq.to_submit > 30 || !lazy) {
-			__cfa_io_flush( ctx->proc );
+			__cfa_io_flush( ctx->proc, false );
 		}
 	}
@@ -515,3 +501,42 @@
 		}
 	}
+
+	#if defined(IO_URING_IDLE)
+		bool __kernel_read(processor * proc, io_future_t & future, char buf[], int fd) {
+			$io_context * ctx = proc->io.ctx;
+			/* paranoid */ verify( ! __preemption_enabled() );
+			/* paranoid */ verify( proc == __cfaabi_tls.this_processor );
+			/* paranoid */ verify( ctx );
+
+			__u32 idx;
+			struct io_uring_sqe * sqe;
+
+			// We can proceed to the fast path
+			if( !__alloc(ctx, &idx, 1) ) return false;
+
+			// Allocation was successful
+			__fill( &sqe, 1, &idx, ctx );
+
+			sqe->opcode = IORING_OP_READ;
+			sqe->user_data = (uintptr_t)&future;
+			sqe->flags = 0;
+			sqe->ioprio = 0;
+			sqe->fd = 0;
+			sqe->off = 0;
+			sqe->fsync_flags = 0;
+			sqe->__pad2[0] = 0;
+			sqe->__pad2[1] = 0;
+			sqe->__pad2[2] = 0;
+			sqe->addr = (uintptr_t)buf;
+			sqe->len = sizeof(uint64_t);
+
+			asm volatile("": : :"memory");
+
+			/* paranoid */ verify( sqe->user_data == (uintptr_t)&future );
+			__submit( ctx, &idx, 1, true );
+
+			/* paranoid */ verify( proc == __cfaabi_tls.this_processor );
+			/* paranoid */ verify( ! __preemption_enabled() );
+		}
+	#endif
 #endif
Index: libcfa/src/concurrency/io/setup.cfa
===================================================================
--- libcfa/src/concurrency/io/setup.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/io/setup.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -32,5 +32,5 @@
 
 	void __cfa_io_start( processor * proc ) {}
-	void __cfa_io_flush( processor * proc ) {}
+	bool __cfa_io_flush( processor * proc, bool ) {}
 	void __cfa_io_stop ( processor * proc ) {}
 
@@ -111,5 +111,5 @@
 		this.ext_sq.empty = true;
 		(this.ext_sq.queue){};
-		__io_uring_setup( this, cl.io.params, proc->idle );
+		__io_uring_setup( this, cl.io.params, proc->idle_fd );
 		__cfadbg_print_safe(io_core, "Kernel I/O : Created ring for io_context %u (%p)\n", this.fd, &this);
 	}
@@ -220,19 +220,21 @@
 		cq.cqes = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes);
 
-		// Step 4 : eventfd
-		// io_uring_register is so f*cking slow on some machine that it
-		// will never succeed if preemption isn't hard blocked
-		__cfadbg_print_safe(io_core, "Kernel I/O : registering %d for completion with ring %d\n", procfd, fd);
-
-		__disable_interrupts_hard();
-
-		int ret = syscall( __NR_io_uring_register, fd, IORING_REGISTER_EVENTFD, &procfd, 1);
-		if (ret < 0) {
-			abort("KERNEL ERROR: IO_URING EVENTFD REGISTER - %s\n", strerror(errno));
-		}
-
-		__enable_interrupts_hard();
-
-		__cfadbg_print_safe(io_core, "Kernel I/O : registered %d for completion with ring %d\n", procfd, fd);
+		#if !defined(IO_URING_IDLE)
+			// Step 4 : eventfd
+			// io_uring_register is so f*cking slow on some machine that it
+			// will never succeed if preemption isn't hard blocked
+			__cfadbg_print_safe(io_core, "Kernel I/O : registering %d for completion with ring %d\n", procfd, fd);
+
+			__disable_interrupts_hard();
+
+			int ret = syscall( __NR_io_uring_register, fd, IORING_REGISTER_EVENTFD, &procfd, 1);
+			if (ret < 0) {
+				abort("KERNEL ERROR: IO_URING EVENTFD REGISTER - %s\n", strerror(errno));
+			}
+
+			__enable_interrupts_hard();
+
+			__cfadbg_print_safe(io_core, "Kernel I/O : registered %d for completion with ring %d\n", procfd, fd);
+		#endif
 
 		// some paranoid checks
Index: libcfa/src/concurrency/io/types.hfa
===================================================================
--- libcfa/src/concurrency/io/types.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/io/types.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -185,6 +185,6 @@
 
 	// Wait for the future to be fulfilled
-	bool wait( io_future_t & this ) {
-		return wait(this.self);
-	}
+	bool wait     ( io_future_t & this ) { return wait     (this.self); }
+	void reset    ( io_future_t & this ) { return reset    (this.self); }
+	bool available( io_future_t & this ) { return available(this.self); }
 }
Index: libcfa/src/concurrency/kernel.cfa
===================================================================
--- libcfa/src/concurrency/kernel.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/kernel.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -34,4 +34,5 @@
 #include "strstream.hfa"
 #include "device/cpu.hfa"
+#include "io/types.hfa"
 
 //Private includes
@@ -124,13 +125,17 @@
 static void __wake_one(cluster * cltr);
 
-static void mark_idle (__cluster_proc_list & idles, processor & proc);
+static void idle_sleep(processor * proc, io_future_t & future, char buf[]);
+static bool mark_idle (__cluster_proc_list & idles, processor & proc);
 static void mark_awake(__cluster_proc_list & idles, processor & proc);
-static [unsigned idle, unsigned total, * processor] query_idles( & __cluster_proc_list idles );
 
 extern void __cfa_io_start( processor * );
 extern bool __cfa_io_drain( processor * );
-extern void __cfa_io_flush( processor * );
+extern bool __cfa_io_flush( processor *, bool wait );
 extern void __cfa_io_stop ( processor * );
 static inline bool __maybe_io_drain( processor * );
+
+#if defined(IO_URING_IDLE) && defined(CFA_HAVE_LINUX_IO_URING_H)
+	extern bool __kernel_read(processor * proc, io_future_t & future, char buf[], int fd);
+#endif
 
 extern void __disable_interrupts_hard();
@@ -148,4 +153,5 @@
 	/* paranoid */ verify( __preemption_enabled() );
 }
+
 
 //=============================================================================================
@@ -163,4 +169,8 @@
 	verify(this);
 
+	io_future_t future; // used for idle sleep when io_uring is present
+	future.self.ptr = 1p;  // mark it as already fulfilled so we know if there is a pending request or not
+	char buf[sizeof(uint64_t)];
+
 	__cfa_io_start( this );
 
@@ -196,5 +206,6 @@
 
 			if( !readyThread ) {
-				__cfa_io_flush( this );
+				__cfa_io_flush( this, false );
+
 				readyThread = __next_thread_slow( this->cltr );
 			}
@@ -210,5 +221,5 @@
 
 				// Push self to idle stack
-				mark_idle(this->cltr->procs, * this);
+				if(!mark_idle(this->cltr->procs, * this)) continue MAIN_LOOP;
 
 				// Confirm the ready-queue is empty
@@ -226,15 +237,98 @@
 				}
 
-				#if !defined(__CFA_NO_STATISTICS__)
-					if(this->print_halts) {
-						__cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl());
+				idle_sleep( this, future, buf );
+
+				// We were woken up, remove self from idle
+				mark_awake(this->cltr->procs, * this);
+
+				// DON'T just proceed, start looking again
+				continue MAIN_LOOP;
+			}
+
+			/* paranoid */ verify( readyThread );
+
+			// Reset io dirty bit
+			this->io.dirty = false;
+
+			// We found a thread run it
+			__run_thread(this, readyThread);
+
+			// Are we done?
+			if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
+
+			if(this->io.pending && !this->io.dirty) {
+				__cfa_io_flush( this, false );
+			}
+
+			#else
+				#warning new kernel loop
+			SEARCH: {
+				/* paranoid */ verify( ! __preemption_enabled() );
+
+				// First, lock the scheduler since we are searching for a thread
+				ready_schedule_lock();
+
+				// Try to get the next thread
+				readyThread = pop_fast( this->cltr );
+				if(readyThread) { ready_schedule_unlock(); break SEARCH; }
+
+				// If we can't find a thread, might as well flush any outstanding I/O
+				if(this->io.pending) { __cfa_io_flush( this, false ); }
+
+				// Spin a little on I/O, just in case
+				for(5) {
+					__maybe_io_drain( this );
+					readyThread = pop_fast( this->cltr );
+					if(readyThread) { ready_schedule_unlock(); break SEARCH; }
+				}
+
+				// no luck, try stealing a few times
+				for(5) {
+					if( __maybe_io_drain( this ) ) {
+						readyThread = pop_fast( this->cltr );
+					} else {
+						readyThread = pop_slow( this->cltr );
 					}
-				#endif
-
-				__cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle);
+					if(readyThread) { ready_schedule_unlock(); break SEARCH; }
+				}
+
+				// still no luck, search for a thread
+				readyThread = pop_search( this->cltr );
+				if(readyThread) { ready_schedule_unlock(); break SEARCH; }
+
+				// Don't block if we are done
+				if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) {
+					ready_schedule_unlock();
+					break MAIN_LOOP;
+				}
+
+				__STATS( __tls_stats()->ready.sleep.halts++; )
+
+				// Push self to idle stack
+				ready_schedule_unlock();
+				if(!mark_idle(this->cltr->procs, * this)) goto SEARCH;
+				ready_schedule_lock();
+
+				// Confirm the ready-queue is empty
+				__maybe_io_drain( this );
+				readyThread = pop_search( this->cltr );
+				ready_schedule_unlock();
+
+				if( readyThread ) {
+					// A thread was found, cancel the halt
+					mark_awake(this->cltr->procs, * this);
+
+					__STATS( __tls_stats()->ready.sleep.cancels++; )
+
+					// continue the main loop
+					break SEARCH;
+				}
+
+				__STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); )
+				__cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle_fd);
 
 				{
 					eventfd_t val;
-					ssize_t ret = read( this->idle, &val, sizeof(val) );
+					ssize_t ret = read( this->idle_fd, &val, sizeof(val) );
 					if(ret < 0) {
 						switch((int)errno) {
@@ -252,9 +346,5 @@
 				}
 
-				#if !defined(__CFA_NO_STATISTICS__)
-					if(this->print_halts) {
-						__cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl());
-					}
-				#endif
+					__STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); )
 
 				// We were woken up, remove self from idle
@@ -265,110 +355,4 @@
 			}
 
-			/* paranoid */ verify( readyThread );
-
-			// Reset io dirty bit
-			this->io.dirty = false;
-
-			// We found a thread run it
-			__run_thread(this, readyThread);
-
-			// Are we done?
-			if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
-
-			if(this->io.pending && !this->io.dirty) {
-				__cfa_io_flush( this );
-			}
-
-			#else
-				#warning new kernel loop
-			SEARCH: {
-				/* paranoid */ verify( ! __preemption_enabled() );
-
-				// First, lock the scheduler since we are searching for a thread
-				ready_schedule_lock();
-
-				// Try to get the next thread
-				readyThread = pop_fast( this->cltr );
-				if(readyThread) { ready_schedule_unlock(); break SEARCH; }
-
-				// If we can't find a thread, might as well flush any outstanding I/O
-				if(this->io.pending) { __cfa_io_flush( this ); }
-
-				// Spin a little on I/O, just in case
-				for(5) {
-					__maybe_io_drain( this );
-					readyThread = pop_fast( this->cltr );
-					if(readyThread) { ready_schedule_unlock(); break SEARCH; }
-				}
-
-				// no luck, try stealing a few times
-				for(5) {
-					if( __maybe_io_drain( this ) ) {
-						readyThread = pop_fast( this->cltr );
-					} else {
-						readyThread = pop_slow( this->cltr );
-					}
-					if(readyThread) { ready_schedule_unlock(); break SEARCH; }
-				}
-
-				// still no luck, search for a thread
-				readyThread = pop_search( this->cltr );
-				if(readyThread) { ready_schedule_unlock(); break SEARCH; }
-
-				// Don't block if we are done
-				if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
-
-				__STATS( __tls_stats()->ready.sleep.halts++; )
-
-				// Push self to idle stack
-				ready_schedule_unlock();
-				mark_idle(this->cltr->procs, * this);
-				ready_schedule_lock();
-
-				// Confirm the ready-queue is empty
-				__maybe_io_drain( this );
-				readyThread = pop_search( this->cltr );
-				ready_schedule_unlock();
-
-				if( readyThread ) {
-					// A thread was found, cancel the halt
-					mark_awake(this->cltr->procs, * this);
-
-					__STATS( __tls_stats()->ready.sleep.cancels++; )
-
-					// continue the main loop
-					break SEARCH;
-				}
-
-				__STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); )
-				__cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle);
-
-				{
-					eventfd_t val;
-					ssize_t ret = read( this->idle, &val, sizeof(val) );
-					if(ret < 0) {
-						switch((int)errno) {
-						case EAGAIN:
-						#if EAGAIN != EWOULDBLOCK
-							case EWOULDBLOCK:
-						#endif
-						case EINTR:
-							// No need to do anything special here, just assume it's a legitimate wake-up
-							break;
-						default:
-							abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) );
-						}
-					}
-				}
-
-					__STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); )
-
-				// We were woken up, remove self from idle
-				mark_awake(this->cltr->procs, * this);
-
-				// DON'T just proceed, start looking again
-				continue MAIN_LOOP;
-			}
-
 		RUN_THREAD:
 			/* paranoid */ verify( ! __preemption_enabled() );
@@ -385,5 +369,5 @@
 
 			if(this->io.pending && !this->io.dirty) {
-				__cfa_io_flush( this );
+				__cfa_io_flush( this, false );
 			}
 
@@ -758,16 +742,13 @@
 
 	// Check if there is a sleeping processor
-	processor * p;
-	unsigned idle;
-	unsigned total;
-	[idle, total, p] = query_idles(this->procs);
+	int fd = __atomic_load_n(&this->procs.fd, __ATOMIC_SEQ_CST);
 
 	// If no one is sleeping, we are done
-	if( idle == 0 ) return;
+	if( fd == 0 ) return;
 
 	// We found a processor, wake it up
 	eventfd_t val;
 	val = 1;
-	eventfd_write( p->idle, val );
+	eventfd_write( fd, val );
 
 	#if !defined(__CFA_NO_STATISTICS__)
@@ -794,17 +775,70 @@
 		eventfd_t val;
 		val = 1;
-		eventfd_write( this->idle, val );
+		eventfd_write( this->idle_fd, val );
 	__enable_interrupts_checked();
 }
 
-static void mark_idle(__cluster_proc_list & this, processor & proc) {
-	/* paranoid */ verify( ! __preemption_enabled() );
-	lock( this );
+static void idle_sleep(processor * this, io_future_t & future, char buf[]) {
+	#if !defined(IO_URING_IDLE) || !defined(CFA_HAVE_LINUX_IO_URING_H)
+		#if !defined(__CFA_NO_STATISTICS__)
+			if(this->print_halts) {
+				__cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl());
+			}
+		#endif
+
+		__cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle_fd);
+
+		{
+			eventfd_t val;
+			ssize_t ret = read( this->idle_fd, &val, sizeof(val) );
+			if(ret < 0) {
+				switch((int)errno) {
+				case EAGAIN:
+				#if EAGAIN != EWOULDBLOCK
+					case EWOULDBLOCK:
+				#endif
+				case EINTR:
+					// No need to do anything special here, just assume it's a legitimate wake-up
+					break;
+				default:
+					abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) );
+				}
+			}
+		}
+
+		#if !defined(__CFA_NO_STATISTICS__)
+			if(this->print_halts) {
+				__cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl());
+			}
+		#endif
+	#else
+		#if !defined(CFA_HAVE_IORING_OP_READ)
+			#error this is only implemented if the read is present
+		#endif
+		// Do we already have a pending read
+		if(available(future)) {
+			// There is no pending read, we need to add one
+			reset(future);
+
+			__kernel_read(this, future, buf, this->idle_fd );
+		}
+
+		__cfa_io_flush( this, true );
+	#endif
+}
+
+static bool mark_idle(__cluster_proc_list & this, processor & proc) {
+	/* paranoid */ verify( ! __preemption_enabled() );
+	if(!try_lock( this )) return false;
 		this.idle++;
 		/* paranoid */ verify( this.idle <= this.total );
 		remove(proc);
 		insert_first(this.idles, proc);
+
+		__atomic_store_n(&this.fd, proc.idle_fd, __ATOMIC_SEQ_CST);
 	unlock( this );
 	/* paranoid */ verify( ! __preemption_enabled() );
+
+	return true;
 }
 
@@ -816,25 +850,12 @@
 		remove(proc);
 		insert_last(this.actives, proc);
+
+		{
+			int fd = 0;
+			if(!this.idles`isEmpty) fd = this.idles`first.idle_fd;
+			__atomic_store_n(&this.fd, fd, __ATOMIC_SEQ_CST);
+		}
+
 	unlock( this );
-	/* paranoid */ verify( ! __preemption_enabled() );
-}
-
-static [unsigned idle, unsigned total, * processor] query_idles( & __cluster_proc_list this ) {
-	/* paranoid */ verify( ! __preemption_enabled() );
-	/* paranoid */ verify( ready_schedule_islocked() );
-
-	for() {
-		uint64_t l = __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST);
-		if( 1 == (l % 2) ) { Pause(); continue; }
-		unsigned idle    = this.idle;
-		unsigned total   = this.total;
-		processor * proc = &this.idles`first;
-		// Compiler fence is unnecessary, but gcc-8 and older incorrectly reorder code without it
-		asm volatile("": : :"memory");
-		if(l != __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST)) { Pause(); continue; }
-		return [idle, total, proc];
-	}
-
-	/* paranoid */ verify( ready_schedule_islocked() );
 	/* paranoid */ verify( ! __preemption_enabled() );
 }
@@ -898,10 +919,10 @@
 		if(head == tail) return false;
 		#if OLD_MAIN
-		ready_schedule_lock();
-		ret = __cfa_io_drain( proc );
-		ready_schedule_unlock();
+			ready_schedule_lock();
+			ret = __cfa_io_drain( proc );
+			ready_schedule_unlock();
 		#else
 			ret = __cfa_io_drain( proc );
-	#endif
+		#endif
 	#endif
 	return ret;
@@ -939,4 +960,5 @@
 			/* paranoid */ verifyf( it, "Unexpected null iterator, at index %u of %u\n", i, count);
 			/* paranoid */ verify( it->local_data->this_stats );
+			// __print_stats( it->local_data->this_stats, cltr->print_stats, "Processor", it->name, (void*)it );
 			__tally_stats( cltr->stats, it->local_data->this_stats );
 			it = &(*it)`next;
@@ -948,4 +970,5 @@
 		// this doesn't solve all problems but does solve many
 		// so it's probably good enough
+		disable_interrupts();
 		uint_fast32_t last_size = ready_mutate_lock();
 
@@ -955,4 +978,5 @@
 		// Unlock the RWlock
 		ready_mutate_unlock( last_size );
+		enable_interrupts();
 	}
 
Index: libcfa/src/concurrency/kernel.hfa
===================================================================
--- libcfa/src/concurrency/kernel.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/kernel.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -100,5 +100,5 @@
 
 	// Idle lock (kernel semaphore)
-	int idle;
+	int idle_fd;
 
 	// Termination synchronisation (user semaphore)
@@ -195,5 +195,8 @@
 struct __cluster_proc_list {
 	// Spin lock protecting the queue
-	volatile uint64_t lock;
+	__spinlock_t lock;
+
+	// FD to use to wake a processor
+	volatile int fd;
 
 	// Total number of processors
Index: libcfa/src/concurrency/kernel/startup.cfa
===================================================================
--- libcfa/src/concurrency/kernel/startup.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/kernel/startup.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -100,4 +100,5 @@
 // Other Forward Declarations
 extern void __wake_proc(processor *);
+extern int cfa_main_returned;							// from interpose.cfa
 
 //-----------------------------------------------------------------------------
@@ -268,4 +269,5 @@
 
 static void __kernel_shutdown(void) {
+	if(!cfa_main_returned) return;
 	/* paranoid */ verify( __preemption_enabled() );
 	disable_interrupts();
@@ -525,6 +527,6 @@
 	this.local_data = 0p;
 
-	this.idle = eventfd(0, 0);
-	if (idle < 0) {
+	this.idle_fd = eventfd(0, 0);
+	if (idle_fd < 0) {
 		abort("KERNEL ERROR: PROCESSOR EVENTFD - %s\n", strerror(errno));
 	}
@@ -540,5 +542,5 @@
 // Not a ctor, it just preps the destruction but should not destroy members
 static void deinit(processor & this) {
-	close(this.idle);
+	close(this.idle_fd);
 }
 
@@ -582,5 +584,5 @@
 // Cluster
 static void ?{}(__cluster_proc_list & this) {
-	this.lock  = 0;
+	this.fd    = 0;
 	this.idle  = 0;
 	this.total = 0;
Index: libcfa/src/concurrency/kernel_private.hfa
===================================================================
--- libcfa/src/concurrency/kernel_private.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/kernel_private.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -39,4 +39,6 @@
 }
 
+// #define IO_URING_IDLE
+
 //-----------------------------------------------------------------------------
 // Scheduler
@@ -149,8 +151,4 @@
 	__atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE);
 }
-
-
-
-
 
 //-----------------------------------------------------------------------
@@ -268,16 +266,27 @@
 	ready_schedule_lock();
 
-	// Simple counting lock, acquired, acquired by incrementing the counter
-	// to an odd number
-	for() {
-		uint64_t l = this.lock;
-		if(
-			(0 == (l % 2))
-			&& __atomic_compare_exchange_n(&this.lock, &l, l + 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
-		) return;
-		Pause();
-	}
-
-	/* paranoid */ verify( ! __preemption_enabled() );
+	lock( this.lock __cfaabi_dbg_ctx2 );
+
+	/* paranoid */ verify( ! __preemption_enabled() );
+}
+
+static inline bool try_lock(__cluster_proc_list & this) {
+	/* paranoid */ verify( ! __preemption_enabled() );
+
+	// Start by locking the global RWlock so that we know no-one is
+	// adding/removing processors while we mess with the idle lock
+	ready_schedule_lock();
+
+	if(try_lock( this.lock __cfaabi_dbg_ctx2 )) {
+		// success
+		/* paranoid */ verify( ! __preemption_enabled() );
+		return true;
+	}
+
+	// failed to lock
+	ready_schedule_unlock();
+
+	/* paranoid */ verify( ! __preemption_enabled() );
+	return false;
 }
 
@@ -285,7 +294,5 @@
 	/* paranoid */ verify( ! __preemption_enabled() );
 
-	/* paranoid */ verify( 1 == (this.lock % 2) );
-	// Simple couting lock, release by incrementing to an even number
-	__atomic_fetch_add( &this.lock, 1, __ATOMIC_SEQ_CST );
+	unlock(this.lock);
 
 	// Release the global lock, which we acquired when locking
Index: libcfa/src/concurrency/monitor.hfa
===================================================================
--- libcfa/src/concurrency/monitor.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/monitor.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -65,4 +65,15 @@
 	free( th );
 }
+
+static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } )
+void adelete( T arr[] ) {
+	if ( arr ) {										// ignore null
+		size_t dim = malloc_size( arr ) / sizeof( T );
+		for ( int i = dim - 1; i >= 0; i -= 1 ) {		// reverse allocation order, must be unsigned
+			^(arr[i]){};								// run destructor
+		} // for
+		free( arr );
+	} // if
+} // adelete
 
 //-----------------------------------------------------------------------------
Index: libcfa/src/concurrency/mutex_stmt.hfa
===================================================================
--- libcfa/src/concurrency/mutex_stmt.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/concurrency/mutex_stmt.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -1,7 +1,4 @@
 #include "bits/algorithm.hfa"
-#include <assert.h>
-#include "invoke.h"
-#include "stdlib.hfa"
-#include <stdio.h>
+#include "bits/defs.hfa"
 
 //-----------------------------------------------------------------------------
Index: libcfa/src/device/cpu.cfa
===================================================================
--- libcfa/src/device/cpu.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/device/cpu.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -144,5 +144,5 @@
 // Count number of cpus in the system
 static int count_cpus(void) {
-	const char * fpath = "/sys/devices/system/cpu/present";
+	const char * fpath = "/sys/devices/system/cpu/online";
 	int fd = open(fpath, 0, O_RDONLY);
 	/* paranoid */ verifyf(fd >= 0, "Could not open file %s", fpath);
Index: libcfa/src/fstream.cfa
===================================================================
--- libcfa/src/fstream.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/fstream.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Sep 21 21:51:38 2021
-// Update Count     : 460
+// Last Modified On : Sun Oct 10 11:23:05 2021
+// Update Count     : 512
 //
 
@@ -28,5 +28,6 @@
 #define IO_MSG "I/O error: "
 
-void ?{}( ofstream & os, void * file ) with(os) {
+// private
+void ?{}( ofstream & os, void * file ) with( os ) {
 	file$ = file;
 	sepDefault$ = true;
@@ -35,5 +36,4 @@
 	prt$ = false;
 	sawNL$ = false;
-	acquired$ = false;
 	sepSetCur$( os, sepGet( os ) );
 	sepSet( os, " " );
@@ -41,30 +41,23 @@
 } // ?{}
 
-// private
-bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
-void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; }
-void sepReset$( ofstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
-const char * sepGetCur$( ofstream & os ) { return os.sepCur$; }
-void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
-bool getNL$( ofstream & os ) { return os.sawNL$; }
-void setNL$( ofstream & os, bool state ) { os.sawNL$ = state; }
-bool getANL$( ofstream & os ) { return os.nlOnOff$; }
-bool getPrt$( ofstream & os ) { return os.prt$; }
-void setPrt$( ofstream & os, bool state ) { os.prt$ = state; }
+inline bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
+inline void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; }
+inline void sepReset$( ofstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
+inline const char * sepGetCur$( ofstream & os ) { return os.sepCur$; }
+inline void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
+inline bool getNL$( ofstream & os ) { return os.sawNL$; }
+inline void setNL$( ofstream & os, bool state ) { os.sawNL$ = state; }
+inline bool getANL$( ofstream & os ) { return os.nlOnOff$; }
+inline bool getPrt$( ofstream & os ) { return os.prt$; }
+inline void setPrt$( ofstream & os, bool state ) { os.prt$ = state; }
+
+inline void lock( ofstream & os ) with( os ) {	lock( os.lock$ ); }
+inline void unlock( ofstream & os ) { unlock( os.lock$ ); }
 
 // public
 void ?{}( ofstream & os ) { os.file$ = 0p; }
-
-void ?{}( ofstream & os, const char name[], const char mode[] ) {
-	open( os, name, mode );
-} // ?{}
-
-void ?{}( ofstream & os, const char name[] ) {
-	open( os, name, "w" );
-} // ?{}
-
-void ^?{}( ofstream & os ) {
-	close( os );
-} // ^?{}
+void ?{}( ofstream & os, const char name[], const char mode[] ) { open( os, name, mode ); }
+void ?{}( ofstream & os, const char name[] ) { open( os, name, "w" ); }
+void ^?{}( ofstream & os ) { close( os ); }
 
 void sepOn( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
@@ -107,21 +100,18 @@
 	if ( &os == &exit ) exit( EXIT_FAILURE );
 	if ( &os == &abort ) abort();
-	if ( os.acquired$ ) { os.acquired$ = false; release( os ); }
 } // ends
 
-bool fail( ofstream & os ) {
-	return os.file$ == 0 || ferror( (FILE *)(os.file$) );
-} // fail
-
-void clear( ofstream & os ) {
-	clearerr( (FILE *)(os.file$) );
-} // clear
-
-int flush( ofstream & os ) {
-	return fflush( (FILE *)(os.file$) );
-} // flush
+bool fail( ofstream & os ) { return os.file$ == 0 || ferror( (FILE *)(os.file$) ); }
+void clear( ofstream & os ) { clearerr( (FILE *)(os.file$) ); }
+int flush( ofstream & os ) { return fflush( (FILE *)(os.file$) ); }
 
 void open( ofstream & os, const char name[], const char mode[] ) {
-	FILE * file = fopen( name, mode );
+	FILE * file;
+    for ( cnt; 10 ) {
+		errno = 0;
+		file = fopen( name, mode );
+	  if ( file != 0p || errno != EINTR ) break;		// timer interrupt ?
+	  if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" );
+    } // for
 	if ( file == 0p ) {
 		throw (Open_Failure){ os };
@@ -131,17 +121,22 @@
 } // open
 
-void open( ofstream & os, const char name[] ) {
-	open( os, name, "w" );
-} // open
-
-void close( ofstream & os ) with(os) {
+void open( ofstream & os, const char name[] ) { open( os, name, "w" ); }
+
+void close( ofstream & os ) with( os ) {
   if ( (FILE *)(file$) == 0p ) return;
   if ( (FILE *)(file$) == (FILE *)stdout || (FILE *)(file$) == (FILE *)stderr ) return;
 
-	if ( fclose( (FILE *)(file$) ) == EOF ) {
+	int ret;
+    for ( cnt; 10 ) {
+		errno = 0;
+		ret = fclose( (FILE *)(file$) );
+	  if ( ret != EOF || errno != EINTR ) break;		// timer interrupt ?
+	  if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" );
+    } // for
+	if ( ret == EOF ) {
 		throw (Close_Failure){ os };
 		// abort | IO_MSG "close output" | nl | strerror( errno );
 	} // if
-	file$ = 0p;
+	file$ = 0p;											// safety after close
 } // close
 
@@ -162,5 +157,12 @@
 	va_list args;
 	va_start( args, format );
-	int len = vfprintf( (FILE *)(os.file$), format, args );
+		
+	int len;
+    for ( cnt; 10 ) {
+		errno = 0;
+		len = vfprintf( (FILE *)(os.file$), format, args );
+	  if ( len != EOF || errno != EINTR ) break;		// timer interrupt ?
+	  if ( cnt == 9 ) abort( "ofstream fmt EINTR spinning exceeded" );
+    } // for
 	if ( len == EOF ) {
 		if ( ferror( (FILE *)(os.file$) ) ) {
@@ -175,17 +177,4 @@
 } // fmt
 
-inline void acquire( ofstream & os ) with(os) {
-	lock( lock$ );										// may increase recursive lock
-	if ( ! acquired$ ) acquired$ = true;				// not locked ?
-	else unlock( lock$ );								// unwind recursive lock at start
-} // acquire
-
-inline void release( ofstream & os ) {
-	unlock( os.lock$ );
-} // release
-
-void ?{}( osacquire & acq, ofstream & os ) { lock( os.lock$ ); &acq.os = &os; }
-void ^?{}( osacquire & acq ) { release( acq.os ); }
-
 static ofstream soutFile = { (FILE *)stdout };
 ofstream & sout = soutFile, & stdout = soutFile;
@@ -205,9 +194,4 @@
 	flush( os );
 	return os;
-	// (ofstream &)(os | '\n');
-	// setPrt$( os, false );							// turn off
-	// setNL$( os, true );
-	// flush( os );
-	// return sepOff( os );							// prepare for next line
 } // nl
 
@@ -217,47 +201,38 @@
 
 // private
-void ?{}( ifstream & is, void * file ) with(is) {
+void ?{}( ifstream & is, void * file ) with( is ) {
 	file$ = file;
 	nlOnOff$ = false;
-	acquired$ = false;
-} // ?{}
+} // ?{}
+
+bool getANL$( ifstream & os ) { return os.nlOnOff$; }
+
+inline void lock( ifstream & os ) with( os ) { lock( os.lock$ ); }
+inline void unlock( ifstream & os ) { unlock( os.lock$ ); }
 
 // public
 void ?{}( ifstream & is ) { is.file$ = 0p; }
-
-void ?{}( ifstream & is, const char name[], const char mode[] ) {
-	open( is, name, mode );
-} // ?{}
-
-void ?{}( ifstream & is, const char name[] ) {
-	open( is, name, "r" );
-} // ?{}
-
-void ^?{}( ifstream & is ) {
-	close( is );
-} // ^?{}
+void ?{}( ifstream & is, const char name[], const char mode[] ) { open( is, name, mode ); }
+void ?{}( ifstream & is, const char name[] ) { open( is, name, "r" ); }
+void ^?{}( ifstream & is ) { close( is ); }
+
+bool fail( ifstream & is ) { return is.file$ == 0p || ferror( (FILE *)(is.file$) ); }
+void clear( ifstream & is ) { clearerr( (FILE *)(is.file$) ); }
 
 void nlOn( ifstream & os ) { os.nlOnOff$ = true; }
 void nlOff( ifstream & os ) { os.nlOnOff$ = false; }
-bool getANL( ifstream & os ) { return os.nlOnOff$; }
-
-bool fail( ifstream & is ) {
-	return is.file$ == 0p || ferror( (FILE *)(is.file$) );
-} // fail
-
-void clear( ifstream & is ) {
-	clearerr( (FILE *)(is.file$) );
-} // clear
-
-void ends( ifstream & is ) {
-	if ( is.acquired$ ) { is.acquired$ = false; release( is ); }
-} // ends
-
-bool eof( ifstream & is ) {
-	return feof( (FILE *)(is.file$) );
-} // eof
+
+void ends( ifstream & is ) {}
+
+bool eof( ifstream & is ) { return feof( (FILE *)(is.file$) ) != 0; }
 
 void open( ifstream & is, const char name[], const char mode[] ) {
-	FILE * file = fopen( name, mode );
+	FILE * file;
+    for ( cnt; 10 ) {
+		errno = 0;
+		file = fopen( name, mode );
+	  if ( file != 0p || errno != EINTR ) break;		// timer interrupt ?
+	  if ( cnt == 9 ) abort( "ifstream open EINTR spinning exceeded" );
+    } // for
 	if ( file == 0p ) {
 		throw (Open_Failure){ is };
@@ -267,17 +242,22 @@
 } // open
 
-void open( ifstream & is, const char name[] ) {
-	open( is, name, "r" );
-} // open
-
-void close( ifstream & is ) with(is) {
+void open( ifstream & is, const char name[] ) { open( is, name, "r" ); }
+
+void close( ifstream & is ) with( is ) {
   if ( (FILE *)(file$) == 0p ) return;
   if ( (FILE *)(file$) == (FILE *)stdin ) return;
 
-	if ( fclose( (FILE *)(file$) ) == EOF ) {
+	int ret;
+    for ( cnt; 10 ) {
+		errno = 0;
+		ret = fclose( (FILE *)(file$) );
+	  if ( ret != EOF || errno != EINTR ) break;		// timer interrupt ?
+	  if ( cnt == 9 ) abort( "ifstream close EINTR spinning exceeded" );
+    } // for
+	if ( ret == EOF ) {
 		throw (Close_Failure){ is };
 		// abort | IO_MSG "close input" | nl | strerror( errno );
 	} // if
-	file$ = 0p;
+	file$ = 0p;											// safety after close
 } // close
 
@@ -308,7 +288,12 @@
 int fmt( ifstream & is, const char format[], ... ) {
 	va_list args;
-
 	va_start( args, format );
-	int len = vfscanf( (FILE *)(is.file$), format, args );
+
+	int len;
+    for () {											// no check for EINTR limit waiting for keyboard input
+		errno = 0;
+		len = vfscanf( (FILE *)(is.file$), format, args );
+	  if ( len != EOF || errno != EINTR ) break;		// timer interrupt ?
+    } // for
 	if ( len == EOF ) {
 		if ( ferror( (FILE *)(is.file$) ) ) {
@@ -319,17 +304,4 @@
 	return len;
 } // fmt
-
-inline void acquire( ifstream & is ) with(is) {
-	lock( lock$ );										// may increase recursive lock
-	if ( ! acquired$ ) acquired$ = true;				// not locked ?
-	else unlock( lock$ );								// unwind recursive lock at start
-} // acquire
-
-inline void release( ifstream & is ) {
-	unlock( is.lock$ );
-} // release
-
-void ?{}( isacquire & acq, ifstream & is ) { lock( is.lock$ ); &acq.is = &is; }
-void ^?{}( isacquire & acq ) { release( acq.is ); }
 
 static ifstream sinFile = { (FILE *)stdin };
Index: libcfa/src/fstream.hfa
===================================================================
--- libcfa/src/fstream.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/fstream.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jul 28 07:35:50 2021
-// Update Count     : 234
+// Last Modified On : Sun Oct 10 09:37:32 2021
+// Update Count     : 243
 //
 
@@ -36,5 +36,4 @@
 	char tupleSeparator$[ofstream_sepSize];
 	multiple_acquisition_lock lock$;
-	bool acquired$;
 }; // ofstream
 
@@ -52,4 +51,7 @@
 bool getPrt$( ofstream & );
 void setPrt$( ofstream &, bool );
+
+void lock( ofstream & );
+void unlock( ofstream & );
 
 // public
@@ -75,17 +77,6 @@
 void open( ofstream &, const char name[] );
 void close( ofstream & );
+
 ofstream & write( ofstream &, const char data[], size_t size );
-
-void acquire( ofstream & );
-void release( ofstream & );
-
-void lock( ofstream & );
-void unlock( ofstream & );
-
-struct osacquire {
-	ofstream & os;
-};
-void ?{}( osacquire & acq, ofstream & );
-void ^?{}( osacquire & acq );
 
 void ?{}( ofstream & );
@@ -110,13 +101,17 @@
 	bool nlOnOff$;
 	multiple_acquisition_lock lock$;
-	bool acquired$;
 }; // ifstream
 
 // Satisfies istream
 
+// private
+bool getANL$( ifstream & );
+
+void lock( ifstream & );
+void unlock( ifstream & );
+
 // public
 void nlOn( ifstream & );
 void nlOff( ifstream & );
-bool getANL( ifstream & );
 void ends( ifstream & );
 int fmt( ifstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
@@ -128,15 +123,7 @@
 void open( ifstream & is, const char name[] );
 void close( ifstream & is );
+
 ifstream & read( ifstream & is, char data[], size_t size );
 ifstream & ungetc( ifstream & is, char c );
-
-void acquire( ifstream & is );
-void release( ifstream & is );
-
-struct isacquire {
-	ifstream & is;
-};
-void ?{}( isacquire & acq, ifstream & is );
-void ^?{}( isacquire & acq );
 
 void ?{}( ifstream & is );
Index: libcfa/src/heap.cfa
===================================================================
--- libcfa/src/heap.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/heap.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -102,5 +102,5 @@
 } // prtUnfreed
 
-extern int cfa_main_returned;							// from bootloader.cf
+extern int cfa_main_returned;							// from interpose.cfa
 extern "C" {
 	void heapAppStart() {								// called by __cfaabi_appready_startup
Index: libcfa/src/interpose.cfa
===================================================================
--- libcfa/src/interpose.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/interpose.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -94,7 +94,10 @@
 } __cabi_libc;
 
+int cfa_main_returned;
+
 extern "C" {
 	void __cfaabi_interpose_startup( void ) {
 		const char *version = 0p;
+		cfa_main_returned = 0;
 
 		preload_libgcc();
Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/iostream.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sat May 15 09:39:21 2021
-// Update Count     : 1342
+// Last Modified On : Sun Oct 10 09:28:17 2021
+// Update Count     : 1345
 //
 
@@ -398,11 +398,4 @@
 		return os;
 	} // nlOff
-} // distribution
-
-forall( ostype & | ostream( ostype ) ) {
-	ostype & acquire( ostype & os ) {
-		acquire( os );									// call void returning
-		return os;
-	} // acquire
 } // distribution
 
@@ -829,5 +822,5 @@
 			fmt( is, "%c", &temp );						// must pass pointer through varg to fmt
 			// do not overwrite parameter with newline unless appropriate
-			if ( temp != '\n' || getANL( is ) ) { c = temp; break; }
+			if ( temp != '\n' || getANL$( is ) ) { c = temp; break; }
 			if ( eof( is ) ) break;
 		} // for
@@ -1035,11 +1028,4 @@
 		return is;
 	} // nlOff
-} // distribution
-
-forall( istype & | istream( istype ) ) {
-	istype & acquire( istype & is ) {
-		acquire( is );									// call void returning
-		return is;
-	} // acquire
 } // distribution
 
Index: libcfa/src/iostream.hfa
===================================================================
--- libcfa/src/iostream.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/iostream.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Apr 28 20:37:56 2021
-// Update Count     : 401
+// Last Modified On : Sun Oct 10 10:02:07 2021
+// Update Count     : 407
 //
 
@@ -58,5 +58,4 @@
 	void close( ostype & );
 	ostype & write( ostype &, const char [], size_t );
-	void acquire( ostype & );							// concurrent access
 }; // ostream
 
@@ -142,8 +141,4 @@
 	ostype & nlOn( ostype & );
 	ostype & nlOff( ostype & );
-} // distribution
-
-forall( ostype & | ostream( ostype ) ) {
-	ostype & acquire( ostype & );
 } // distribution
 
@@ -296,8 +291,9 @@
 
 trait basic_istream( istype & ) {
-	bool getANL( istype & );							// get scan newline (on/off)
+	// private
+	bool getANL$( istype & );							// get scan newline (on/off)
+	// public
 	void nlOn( istype & );								// read newline
 	void nlOff( istype & );								// scan newline
-
 	void ends( istype & os );							// end of output statement
 	int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
@@ -312,5 +308,4 @@
 	void close( istype & is );
 	istype & read( istype &, char [], size_t );
-	void acquire( istype & );							// concurrent access
 }; // istream
 
@@ -379,8 +374,4 @@
 } // distribution
 
-forall( istype & | istream( istype ) ) {
-	istype & acquire( istype & );
-} // distribution
-
 // *********************************** manipulators ***********************************
 
Index: libcfa/src/strstream.cfa
===================================================================
--- libcfa/src/strstream.cfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/strstream.cfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -10,9 +10,10 @@
 // Created On       : Thu Apr 22 22:24:35 2021
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 27 20:59:53 2021
-// Update Count     : 78
+// Last Modified On : Sun Oct 10 16:13:20 2021
+// Update Count     : 101
 // 
 
 #include "strstream.hfa"
+#include "fstream.hfa"									// abort
 
 #include <stdio.h>										// vsnprintf
@@ -30,14 +31,14 @@
 
 // private
-bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
-void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
-void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
-const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
-void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
-bool getNL$( ostrstream & os ) { return os.sawNL$; }
-void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }
-bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
-bool getPrt$( ostrstream & os ) { return os.prt$; }
-void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }
+inline bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
+inline void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }
+inline void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
+inline const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }
+inline void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
+inline bool getNL$( ostrstream & os ) { return os.sawNL$; }
+inline void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }
+inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; }
+inline bool getPrt$( ostrstream & os ) { return os.prt$; }
+inline void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }
 
 // public
@@ -128,4 +129,6 @@
 // *********************************** istrstream ***********************************
 
+// private
+bool getANL$( istrstream & is ) { return is.nlOnOff$; }
 
 // public
@@ -136,14 +139,27 @@
 } // ?{}
 
-bool getANL( istrstream & is ) { return is.nlOnOff$; }
 void nlOn( istrstream & is ) { is.nlOnOff$ = true; }
 void nlOff( istrstream & is ) { is.nlOnOff$ = false; }
 
-void ends( istrstream & is ) {
-} // ends
+void ends( istrstream & is ) {}
+bool eof( istrstream & is ) { return false; }
 
-int eof( istrstream & is ) {
-	return 0;
-} // eof
+int fmt( istrstream & is, const char format[], ... ) with(is) {
+	va_list args;
+	va_start( args, format );
+	// THIS DOES NOT WORK BECAUSE VSSCANF RETURNS NUMBER OF VALUES READ VERSUS BUFFER POSITION SCANNED.
+	int len = vsscanf( buf$ + cursor$, format, args );
+	va_end( args );
+	if ( len == EOF ) {
+		abort | IO_MSG "invalid read";
+	} // if
+	// SKULLDUGGERY: This hack skips over characters read by vsscanf by moving to the next whitespace but it does not
+	// handle C reads with wdi manipulators that leave the cursor at a non-whitespace character.
+	for ( ; buf$[cursor$] != ' ' && buf$[cursor$] != '\t' && buf$[cursor$] != '\0'; cursor$ += 1 ) {
+		//printf( "X \'%c\'\n", buf$[cursor$] );
+	} // for
+	if ( buf$[cursor$] != '\0' ) cursor$ += 1;	// advance to whitespace
+	return len;
+} // fmt
 
 istrstream &ungetc( istrstream & is, char c ) {
@@ -154,18 +170,4 @@
 } // ungetc
 
-int fmt( istrstream & is, const char format[], ... ) {
-	va_list args;
-	va_start( args, format );
-	// This does not work because vsscanf does not return buffer position.
-	int len = vsscanf( is.buf$ + is.cursor$, format, args );
-	va_end( args );
-	if ( len == EOF ) {
-		int j;
-		printf( "X %d%n\n", len, &j );
-	} // if
-	is.cursor$ += len;
-	return len;
-} // fmt
-
 // Local Variables: //
 // tab-width: 4 //
Index: libcfa/src/strstream.hfa
===================================================================
--- libcfa/src/strstream.hfa	(revision 94647b0b7573effbb2f73c03b06886b22af1249a)
+++ libcfa/src/strstream.hfa	(revision 7770cc8a0981a8a6485f2ec3ee49b6a51f60afde)
@@ -10,6 +10,6 @@
 // Created On       : Thu Apr 22 22:20:59 2021
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 27 20:58:50 2021
-// Update Count     : 41
+// Last Modified On : Sun Oct 10 10:14:22 2021
+// Update Count     : 47
 // 
 
@@ -85,14 +85,17 @@
 // Satisfies basic_istream
 
+// private
+bool getANL$( istrstream & );
+
 // public
-bool getANL( istrstream & );
 void nlOn( istrstream & );
 void nlOff( istrstream & );
 void ends( istrstream & );
+
 int fmt( istrstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
-istrstream & ungetc( istrstream & is, char c );
-int eof( istrstream & is );
+istrstream & ungetc( istrstream &, char );
+bool eof( istrstream & );
 
-void ?{}( istrstream & is, char buf[] );
+void ?{}( istrstream &, char buf[] );
 
 // Local Variables: //
