Index: benchmark/readyQ/cycle.cfa
===================================================================
--- benchmark/readyQ/cycle.cfa	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ benchmark/readyQ/cycle.cfa	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -85,5 +85,5 @@
 		}
 
-		printf("Duration (ms)        : %'ld\n", (end - start)`dms);
+		printf("Duration (ms)        : %'lf\n", (end - start)`dms);
 		printf("Number of processors : %'d\n", nprocs);
 		printf("Number of threads    : %'d\n", tthreads);
Index: benchmark/readyQ/locality.cfa
===================================================================
--- benchmark/readyQ/locality.cfa	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ benchmark/readyQ/locality.cfa	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -126,6 +126,6 @@
 // ==================================================
 // Do some work by accessing 'cnt' cells in the array
-__attribute__((noinline)) void work(MyData & data, size_t cnt, uint64_t & state) {
-	for (cnt) {
+__attribute__((noinline)) void work(MyData & data, size_t cnt_, uint64_t & state) {
+	for (cnt_) {
 		access(data, __xorshift64(state));
 	}
@@ -200,4 +200,8 @@
 
 	if( nspots == 0 ) { nspots = nthreads - nprocs; }
+	if( nspots == 0 ) {
+		fprintf(stderr, "--nspots must be set or --nthreads set to something bigger than --nprocs\n");
+		exit(EXIT_FAILURE);
+	}
 
 	Time start, end;
Index: benchmark/readyQ/yield.cpp
===================================================================
--- benchmark/readyQ/yield.cpp	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ benchmark/readyQ/yield.cpp	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -29,5 +29,5 @@
 #include "libfibre/fibre.h"
 
-FibreBarrier * barrier;
+FredBarrier * barrier;
 struct __attribute__((aligned(128))) counter_t {
 	int value = 0;
@@ -66,5 +66,4 @@
 
 		const char * arg = optarg ? optarg : "";
-		size_t len = 0;
 		char * end;
 		switch(opt) {
@@ -111,5 +110,5 @@
 
 		FibreInit();
-		barrier = new FibreBarrier(nthreads + 1);
+		barrier = new FredBarrier(nthreads + 1);
 		{
 			Context::CurrCluster().addWorkers(nprocs);
Index: doc/theses/andrew_beach_MMath/performance.tex
===================================================================
--- doc/theses/andrew_beach_MMath/performance.tex	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ doc/theses/andrew_beach_MMath/performance.tex	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -160,4 +160,16 @@
 % Match All     &   3719462155 &   43294042 &   3223004977 &  1286054154 &   623887874 \\
 % Match None    &   4971630929 &   55311709 &   9481225467 &  1310251289 &   623752624 \\
+%
+% run-algol-04-a
+% --------------
+% Raise Empty   & 0.0 & 0.0 &  3250260945 & 0.0 & 0.0 \\
+% Raise D'tor   & 0.0 & 0.0 & 29017675113 & N/A & N/A \\
+% Raise Finally & 0.0 & 0.0 &         N/A & 0.0 & 0.0 \\
+% Raise Other   & 0.0 & 0.0 & 24411823773 & 0.0 & 0.0 \\
+% Cross Handler & 0.0 & 0.0 &      769334 & 0.0 & 0.0 \\
+% Cross Finally & 0.0 & N/A &         N/A & 0.0 & 0.0 \\
+% Match All     & 0.0 & 0.0 &  3254283504 & 0.0 & 0.0 \\
+% Match None    & 0.0 & 0.0 &  9476060146 & 0.0 & 0.0 \\
+
 \begin{tabular}{|l|c c c c c|}
 \hline
@@ -196,4 +208,16 @@
 % Match All     &   3189512499 &   39124453 &   2667795989 &  1525889031 &   733785613 \\
 % Match None    &   4094675477 &   48749857 &   7850618572 &  1566713577 &   733478963 \\
+%
+% run-plg7a-04-a
+% --------------
+% 0.0 are unfilled.
+% Raise Empty   & 0.0 & 0.0 &  2770781479 & 0.0 & 0.0 \\
+% Raise D'tor   & 0.0 & 0.0 & 23530084907 & N/A & N/A \\
+% Raise Finally & 0.0 & 0.0 &         N/A & 0.0 & 0.0 \\
+% Raise Other   & 0.0 & 0.0 & 23816827982 & 0.0 & 0.0 \\
+% Cross Handler & 0.0 & 0.0 &     1422188 & 0.0 & 0.0 \\
+% Cross Finally & 0.0 & N/A &         N/A & 0.0 & 0.0 \\
+% Match All     & 0.0 & 0.0 &  2671989778 & 0.0 & 0.0 \\
+% Match None    & 0.0 & 0.0 &  7829059869 & 0.0 & 0.0 \\
 
 % PLG7A (in seconds)
@@ -202,12 +226,4 @@
               & \CFA (Terminate) & \CFA (Resume) & \Cpp & Java & Python \\
 \hline
-% Raise Empty   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
-% Raise D'tor   & 0.0 & 0.0 & 0.0 & N/A & N/A \\
-% Raise Finally & 0.0 & 0.0 & N/A & 0.0 & 0.0 \\
-% Raise Other   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
-% Cross Handler & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
-% Cross Finally & 0.0 & N/A & N/A & 0.0 & 0.0 \\
-% Match All     & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
-% Match None    & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
 Raise Empty   & 0.0 & 0.0 & 0.0 & 0.0 & 0.0 \\
 Raise D'tor   & 0.0 & 0.0 & 0.0 & N/A & N/A \\
@@ -231,16 +247,23 @@
 
 This means that while \CFA does not actually keep up with Python in every
-case it is no worse than roughly half the speed of \Cpp. This is good
+case it is usually no worse than roughly half the speed of \Cpp. This is good
 enough for the prototyping purposes of the project.
 
-One difference not shown is that optimizations in \CFA is very fragile.
-The \CFA compiler uses gcc as part of its complation process and the version
-of gcc could change the speed of some of the benchmarks by 10 times or more.
-Similar changes to g++ for the \Cpp benchmarks had no significant changes.
-Because of the connection between gcc and g++; this suggests it is not the
-optimizations that are changing but how the optimizer is detecting if the
-optimizations can be applied. So the optimizations are always applied in
-g++, but only newer versions of gcc can detect that they can be applied in
-the more complex \CFA code.
+The test case where \CFA falls short is Raise Other, the case where the
+stack is unwound including a bunch of non-matching handlers.
+This slowdown seems to come from missing optimizations,
+the results above came from gcc/g++ 10 (gcc as \CFA backend or g++ for \Cpp)
+but the results change if they are run in gcc/g++ 9 instead.
+Importantly, there is a huge slowdown in \Cpp's results bringing that brings
+\CFA's performace back in that roughly half speed area. However many other
+\CFA benchmarks increase their run-time by a similar amount falling far
+behind their \Cpp counter-parts.
+
+This suggests that the performance issue in Raise Other is just an
+optimization not being applied. Later versions of gcc may be able to
+optimize this case further, at least down to the half of \Cpp mark.
+A \CFA compiler that directly produced assembly could do even better as it
+would not have to work across some of \CFA's current abstractions, like
+the try terminate function.
 
 Resumption exception handling is also incredibly fast. Often an order of
Index: libcfa/prelude/bootloader.cf
===================================================================
--- libcfa/prelude/bootloader.cf	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ libcfa/prelude/bootloader.cf	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -3,4 +3,5 @@
 char ** cfa_args_argv;
 char ** cfa_args_envp;
+int cfa_main_returned = 0;
 
 int main(int argc, char* argv[], char* envp[]) {
@@ -8,4 +9,6 @@
 	cfa_args_argv = argv;
 	cfa_args_envp = envp;
-	return invoke_main(argc, argv, envp);
+	int ret = invoke_main(argc, argv, envp);
+	cfa_main_returned = 1;
+	return ret;
 }
Index: libcfa/src/concurrency/invoke.h
===================================================================
--- libcfa/src/concurrency/invoke.h	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ libcfa/src/concurrency/invoke.h	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -170,4 +170,6 @@
 		bool corctx_flag;
 
+		int last_cpu;
+
 		//SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it
 
Index: libcfa/src/concurrency/kernel.cfa
===================================================================
--- libcfa/src/concurrency/kernel.cfa	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ libcfa/src/concurrency/kernel.cfa	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -394,4 +394,14 @@
 	__builtin_prefetch( thrd_dst->context.SP );
 
+	int curr = __kernel_getcpu();
+	if(thrd_dst->last_cpu != curr) {
+		int64_t l = thrd_dst->last_cpu;
+		int64_t c = curr;
+		int64_t v = (l << 32) | c;
+		__push_stat( __tls_stats(), v, false, "Processor", this );
+	}
+
+	thrd_dst->last_cpu = curr;
+
 	__cfadbg_print_safe(runtime_core, "Kernel : core %p running thread %p (%s)\n", this, thrd_dst, thrd_dst->self_cor.name);
 
@@ -470,5 +480,4 @@
 				#if !defined(__CFA_NO_STATISTICS__)
 					__tls_stats()->ready.threads.threads++;
-					__push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", this );
 				#endif
 				// This is case 2, the racy case, someone tried to run this thread before it finished blocking
@@ -488,5 +497,4 @@
 	#if !defined(__CFA_NO_STATISTICS__)
 		__tls_stats()->ready.threads.threads--;
-		__push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", this );
 	#endif
 
@@ -570,10 +578,8 @@
 				__tls_stats()->ready.threads.extunpark++;
 			}
-			__push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", kernelTLS().this_processor );
 		}
 		else {
 			__atomic_fetch_add(&cl->stats->ready.threads.threads, 1, __ATOMIC_RELAXED);
 			__atomic_fetch_add(&cl->stats->ready.threads.extunpark, 1, __ATOMIC_RELAXED);
-			__push_stat( cl->stats, cl->stats->ready.threads.threads, true, "Cluster", cl );
 		}
 	#endif
Index: libcfa/src/concurrency/kernel.hfa
===================================================================
--- libcfa/src/concurrency/kernel.hfa	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ libcfa/src/concurrency/kernel.hfa	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -67,4 +67,5 @@
 		unsigned target;
 		unsigned last;
+		unsigned cnt;
 		unsigned long long int cutoff;
 	} rdq;
Index: libcfa/src/concurrency/kernel/startup.cfa
===================================================================
--- libcfa/src/concurrency/kernel/startup.cfa	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ libcfa/src/concurrency/kernel/startup.cfa	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -478,4 +478,5 @@
 	state = Start;
 	self_cor{ info };
+	last_cpu = __kernel_getcpu();
 	curr_cor = &self_cor;
 	curr_cluster = mainCluster;
Index: libcfa/src/concurrency/ready_queue.cfa
===================================================================
--- libcfa/src/concurrency/ready_queue.cfa	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ libcfa/src/concurrency/ready_queue.cfa	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -345,17 +345,10 @@
 			/* paranoid */ verify(lanes.count < 65536); // The following code assumes max 65536 cores.
 			/* paranoid */ verify(map.count < 65536); // The following code assumes max 65536 cores.
-			uint64_t chaos = __tls_rand();
-			uint64_t high_chaos = (chaos >> 32);
-			uint64_t  mid_chaos = (chaos >> 16) & 0xffff;
-			uint64_t  low_chaos = chaos & 0xffff;
-
-			unsigned me = map.self;
-			unsigned cpu_chaos = map.start + (mid_chaos % map.count);
-			bool global = cpu_chaos == me;
-
-			if(global) {
-				proc->rdq.target = high_chaos % lanes.count;
+
+			if(0 == (__tls_rand() % 10_000)) {
+				proc->rdq.target = __tls_rand() % lanes.count;
 			} else {
-				proc->rdq.target = (cpu_chaos * READYQ_SHARD_FACTOR) + (low_chaos % READYQ_SHARD_FACTOR);
+				unsigned cpu_chaos = map.start + (__tls_rand() % map.count);
+				proc->rdq.target = (cpu_chaos * READYQ_SHARD_FACTOR) + (__tls_rand() % READYQ_SHARD_FACTOR);
 				/* paranoid */ verify(proc->rdq.target >= (map.start * READYQ_SHARD_FACTOR));
 				/* paranoid */ verify(proc->rdq.target <  ((map.start + map.count) * READYQ_SHARD_FACTOR));
Index: libcfa/src/concurrency/thread.cfa
===================================================================
--- libcfa/src/concurrency/thread.cfa	(revision 4f89e7b1d193413b9c5683d17890be98ac971f0f)
+++ libcfa/src/concurrency/thread.cfa	(revision 50b29d9928d45663d1aba6fee8a1248f81bf095f)
@@ -34,4 +34,5 @@
 	preempted = __NO_PREEMPTION;
 	corctx_flag = false;
+	last_cpu = __kernel_getcpu();
 	curr_cor = &self_cor;
 	self_mon.owner = &this;
