Index: benchmark/readyQ/locality.go
===================================================================
--- benchmark/readyQ/locality.go	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
+++ benchmark/readyQ/locality.go	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -0,0 +1,124 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"math/rand"
+	"os"
+	"sync/atomic"
+	"time"
+	"golang.org/x/text/language"
+	"golang.org/x/text/message"
+)
+
+func handshake(stop chan struct {}, c chan [] uint64, data [] uint64, share bool) (bool, [] uint64) {
+	var s [] uint64 = data
+	if !share {
+		s = nil
+	}
+
+	// send the data
+	select {
+	case <- stop:
+		return true, nil
+	case c <- s:
+	}
+
+	// get the new data chunk
+	select {
+	case <- stop:
+		return true, nil
+	case n := <- c:
+		if share {
+			return false, n
+		}
+		return false, data
+	}
+}
+
+func local(result chan uint64, start chan struct{}, stop chan struct{}, size uint64, cnt uint64, channels []chan [] uint64, chan_cnt uint64, share bool) {
+	var data [] uint64
+	data = make([]uint64, size)
+	for i := uint64(0); i < size; i++ {
+		data[i] = 0
+	}
+	count := uint64(0)
+	<- start
+	for true {
+		for i := uint64(0); i < cnt; i++ {
+			data[rand.Uint64() % size] += 1
+		}
+
+		i := rand.Uint64() % chan_cnt
+		var closed bool
+		closed, data = handshake(stop, channels[i], data, share)
+		count += 1
+
+		if  closed { break }
+		if !clock_mode && count >= stop_count { break }
+	}
+
+	atomic.AddInt64(&threads_left, -1);
+	result <- count
+}
+
+func main() {
+
+	work_sizeOpt := flag.Uint64("w", 2    , "Number of words (uint64) per threads")
+	countOpt     := flag.Uint64("c", 2    , "Number of words (uint64) to touch")
+	shareOpt     := flag.Bool  ("s", false, "Pass the work data to the next thread when blocking")
+
+	bench_init()
+
+	size  := *work_sizeOpt
+	cnt   := *countOpt
+	share := *shareOpt
+
+	if ! (nthreads > nprocs) {
+		fmt.Fprintf(os.Stderr, "Must have more threads than procs\n")
+		os.Exit(1)
+	}
+
+	barrierStart := make(chan struct{})
+	barrierStop  := make(chan struct{})
+	threads_left = int64(nthreads)
+	result  := make(chan uint64)
+	channels := make([]chan [] uint64, nthreads - nprocs)
+	for i := range channels {
+		channels[i] = make(chan [] uint64, 1)
+	}
+
+	for i := 0; i < nthreads; i++ {
+		go local(result, barrierStart, barrierStop, size, cnt, channels, uint64(nthreads - nprocs), share)
+	}
+	fmt.Printf("Starting\n");
+
+	start := time.Now()
+	close(barrierStart)
+
+	wait(start, true);
+
+	close(barrierStop)
+	end := time.Now()
+	delta := end.Sub(start)
+
+	fmt.Printf("\nDone\n")
+
+	global_counter := uint64(0)
+	for i := 0; i < nthreads; i++ {
+		global_counter += <- result
+	}
+
+	p := message.NewPrinter(language.English)
+	p.Printf("Duration (ms)          : %f\n", delta.Seconds());
+	p.Printf("Number of processors   : %d\n", nprocs);
+	p.Printf("Number of threads      : %d\n", nthreads);
+	p.Printf("Work size (64bit words): %d\n", size);
+	p.Printf("Total Operations(ops)  : %15d\n", global_counter)
+	p.Printf("Ops per second         : %18.2f\n", float64(global_counter) / delta.Seconds())
+	p.Printf("ns per ops             : %18.2f\n", float64(delta.Nanoseconds()) / float64(global_counter))
+	p.Printf("Ops per threads        : %15d\n", global_counter / uint64(nthreads))
+	p.Printf("Ops per procs          : %15d\n", global_counter / uint64(nprocs))
+	p.Printf("Ops/sec/procs          : %18.2f\n", (float64(global_counter) / float64(nprocs)) / delta.Seconds())
+	p.Printf("ns per ops/procs       : %18.2f\n", float64(delta.Nanoseconds()) / (float64(global_counter) / float64(nprocs)))
+}
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/Makefile
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/Makefile	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/Makefile	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -1,6 +1,18 @@
-all: gui-proto
+all: gui-proto-pthread gui-proto-fibre gui-proto-cforall
+
+PRECIOUS: thrdlib/libthrd-pthread.so thrdlib/libthrd-fibre.so thrdlib/libthrd-cforall.so
 
 CXXFLAGS = -fpic -g -O0 -I.
 
-gui-proto: proto-gui/main.o thrdlib/thread.o
-	$(CXX) -pthread -ldl -o ${@} ${^} -ftls-model=initial-exec
+thrdlib/libthrd-%.so:
+	+${MAKE} -C thrdlib libthrd-$*.so
+
+gui-proto-%: proto-gui/main.o thrdlib/libthrd-%.so Makefile
+	$(CXX) -Lthrdlib -Wl,--rpath,thrdlib -pthread -o $@ $< -lthrd-$*
+
+CFAINC=${HOME}/local/include/cfa-dev
+CFALIB=${HOME}/local/lib/cfa-dev/x64-debug
+CFAFLAGS=-z execstack -ftls-model=initial-exec -L${CFALIB} -Wl,-rpath,${CFALIB}
+
+gui-proto-cforall: proto-gui/main.o thrdlib/libthrd-cforall.so Makefile
+	$(CXX) -Lthrdlib -Wl,--rpath,thrdlib ${CFAFLAGS} -pthread -o $@ $< -lthrd-cforall -Wl,--push-state,--no-as-needed -lcfathread -lcfa -ldl -lm -Wl,--pop-state
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/proto-gui/main.cpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/proto-gui/main.cpp	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/proto-gui/main.cpp	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -11,27 +11,4 @@
 #include <getopt.h>
 using thrdlib::thread_t;
-
-
-extern __attribute__((aligned(128))) thread_local struct {
-	void * volatile this_thread;
-	void * volatile this_processor;
-	void * volatile this_stats;
-
-	struct {
-		volatile unsigned short disable_count;
-		volatile bool enabled;
-		volatile bool in_progress;
-	} preemption_state;
-
-	#if defined(__SIZEOF_INT128__)
-		__uint128_t rand_seed;
-	#else
-		uint64_t rand_seed;
-	#endif
-	struct {
-		uint64_t fwd_seed;
-		uint64_t bck_seed;
-	} ready_rng;
-} kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
 
 //--------------------
@@ -148,4 +125,15 @@
 }
 
+typedef uint64_t __wyhash64_state_t;
+static inline uint64_t __wyhash64( __wyhash64_state_t & state ) {
+	state += 0x60bee2bee120fc15;
+	__uint128_t tmp;
+	tmp = (__uint128_t) state * 0xa3b195354a39b70d;
+	uint64_t m1 = (tmp >> 64) ^ tmp;
+	tmp = (__uint128_t)m1 * 0x1b03738712fad5c9;
+	uint64_t m2 = (tmp >> 64) ^ tmp;
+	return m2;
+}
+
 void Simulator( thread_t self ) {
 	for(unsigned i = 0; i < nproduce; i++) {
@@ -156,8 +144,10 @@
 		}
 
+		__wyhash64_state_t state = 0;
+
 		// Write the frame information
 		frame.number = i;
 		for( unsigned x = 0; x < fsize; x++ ) {
-			frame.data[x] = i;
+			frame.data[x] = __wyhash64(state);
 		}
 		std::cout << "Simulated " << i << std::endl;
@@ -187,5 +177,5 @@
 
 		std::cout << "Rendered " << i << std::endl;
-		assert(total == i * fsize);
+		// assert(total == i * fsize);
 
 		// Release
@@ -201,8 +191,6 @@
 int main(int argc, char * argv[]) {
 	nframes  = 3;
-	fsize    = 1000;
+	fsize    = 3840 * 2160 * 4 * 4;
 	nproduce = 60;
-
-	const char * framework;
 
 	for(;;) {
@@ -222,11 +210,4 @@
 			// Exit Case
 			case -1:
-				/* paranoid */ assert(optind <= argc);
-				if( optind == argc ) {
-					std::cerr << "Must specify a framework" << std::endl;
-					goto usage;
-
-				}
-				framework = argv[optind];
 				goto run;
 			case 'b':
@@ -261,5 +242,5 @@
 				std::cerr << opt << std::endl;
 			usage:
-				std::cerr << "Usage: " << argv[0] << " [options] framework" << std::endl;
+				std::cerr << "Usage: " << argv[0] << " [options]" << std::endl;
 				std::cerr << std::endl;
 				std::cerr << "  -b, --buff=COUNT    Number of frames to buffer" << std::endl;
@@ -270,6 +251,4 @@
 	}
 	run:
-	assert( framework );
-
 	frames.reset(new Frame[nframes]);
 	for(unsigned i = 0; i < nframes; i++) {
@@ -280,5 +259,5 @@
 	std::cout << "(Buffering " << nframes << ")" << std::endl;
 
-	thrdlib::init( framework, 2 );
+	thrdlib::init( 2 );
 
 	thread_t stats     = thrdlib::create( Stats );
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/Makefile
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/Makefile	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/Makefile	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -1,14 +1,14 @@
-all: fibre.so pthread.so cforall.so
+all: fibre.so libthrd-pthread.so.so cforall.so
 
 clean:
-	rm -rf fibre.so pthread.so
+	rm -rf fibre.so libthrd-pthread.so.so cforall.so
 
 CXXFLAGS=-Wall -Wextra -O3 -g -fpic -std=c++17 -pthread -ftls-model=initial-exec
 
-pthread.so: pthread.cpp Makefile
-	$(CXX) $(CXXFLAGS) -shared -o ${@} ${<}
+libthrd-pthread.so: thread.cpp thread.hpp Makefile
+	$(CXX) $(CXXFLAGS) -shared -o $@ $< -DWITH_PTHREADS
 
-fibre.so: fibre.cpp Makefile
-	$(CXX) $(CXXFLAGS) -shared -o ${@} ${<} -lfibre
+libthrd-fibre.so: thread.cpp thread.hpp Makefile
+	$(CXX) $(CXXFLAGS) -shared -o $@ $< -DWITH_LIBFIBRE -lfibre
 
 CFAINC=${HOME}/local/include/cfa-dev
@@ -16,4 +16,4 @@
 CFAFLAGS=-z execstack -I${CFAINC} -I${CFAINC}/concurrency -L${CFALIB} -Wl,-rpath,${CFALIB}
 
-cforall.so: cforall.cpp Makefile
-	$(CXX) $(CXXFLAGS) $(CFAFLAGS) -shared -o ${@} ${<} -lcfathread -lcfa -ldl -lm
+libthrd-cforall.so: thread.cpp thread.hpp Makefile
+	$(CXX) $(CXXFLAGS) $(CFAFLAGS) -shared -o $@ $< -DWITH_CFORALL -Wl,--push-state,--no-as-needed -lcfathread -lcfa -ldl -lm -Wl,--pop-state
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.hpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.hpp	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.hpp	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -1,2 +1,4 @@
+#pragma once
+
 #include <pthread.h>
 #include <errno.h>
@@ -97,3 +99,4 @@
 	// Basic kernel features
 	void thrdlib_init( int ) {}
+	void thrdlib_clean( void ) {}
 }
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.cpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.cpp	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.cpp	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -1,68 +1,28 @@
-#include "thread.hpp"
+#if !defined(WITH_PTHREADS) && !defined(WITH_LIBFIBRE) && !defined(WITH_CFORALL)
+#error must define WITH_PTHREADS, WITH_LIBFIBRE or WITH_CFORALL
+#endif
 
-#include <cstdarg>										// va_start, va_end
-#include <cstdio>
-#include <cstring>										// strlen
-extern "C" {
-	#include <unistd.h>										// _exit, getpid
-	#include <signal.h>
-	#include <dlfcn.h>										// dlopen, dlsym
-	#include <execinfo.h>									// backtrace, messages
-}
+#ifdef WITH_PTHREADS
+#include "pthread.hpp"
+#endif
+#ifdef WITH_LIBFIBRE
+#include "fibre.hpp"
+#endif
+#ifdef WITH_CFORALL
+#include "cforall.hpp"
+#endif
 
-#include <iostream>
-#include <string>
+namespace thrdlib {
+	//--------------------
+	// Basic thread support
+	void * create( void (*main)( void * ) ) { return (thread_t)thrdlib_create(  (void (*)( thread_t )) main ); }
+	void join  ( void * handle ) { thrdlib_join  ((thread_t)handle); }
+	void park  ( void * handle ) { thrdlib_park  ((thread_t)handle); }
+	void unpark( void * handle ) { thrdlib_unpark((thread_t)handle); }
+	void yield( void )  { thrdlib_yield(); }
 
-using thrdlib::thread_t;
-
-thread_t (*thrdlib::create)( void (*main)( thread_t ) ) = nullptr;
-void (*thrdlib::join)( thread_t handle ) = nullptr;
-void (*thrdlib::park)( thread_t handle ) = nullptr;
-void (*thrdlib::unpark)( thread_t handle ) = nullptr;
-void (*thrdlib::yield)( void ) = nullptr;
-void (*lib_clean)(void) = nullptr;
-
-typedef void (*fptr_t)();
-static fptr_t open_symbol( void * library, const char * symbol, bool required ) {
-	void * ptr = dlsym( library, symbol );
-
-	const char * error = dlerror();
-	if ( required && error ) {
-		std::cerr << "Fetching symbol '" << symbol << "' failed with error '" << error << "'\n";
-		std::abort();
-	}
-
-	return (fptr_t)ptr;
-}
-
-//--------------------
-// Basic kernel features
-void thrdlib::init( const char * name, int procs ) {
-	std::string file = __FILE__;
-	std::size_t found = file.find_last_of("/");
-  	std::string libname = file.substr(0,found+1) + name + ".so";
-
-	std::cout << "Use framework " << name << "(" << libname << ")\n";
-
-	void * library = dlopen( libname.c_str(), RTLD_NOW );
-	if ( const char * error = dlerror() ) {
-		std::cerr << "Could not open library '" << libname << "' from name '" << name <<"'\n";
-		std::cerr << "Error was : '" << error << "'\n";
-		std::abort();
-	}
-
-	void (*lib_init)( int ) = (void (*)( int ))open_symbol( library, "thrdlib_init", false );
-	lib_clean = open_symbol( library, "thrdlib_clean" , false );
-
-	thrdlib::create = (typeof(thrdlib::create))open_symbol( library, "thrdlib_create", true  );
-	thrdlib::join   = (typeof(thrdlib::join  ))open_symbol( library, "thrdlib_join"  , true  );
-	thrdlib::park   = (typeof(thrdlib::park  ))open_symbol( library, "thrdlib_park"  , true  );
-	thrdlib::unpark = (typeof(thrdlib::unpark))open_symbol( library, "thrdlib_unpark", true  );
-	thrdlib::yield  = (typeof(thrdlib::yield ))open_symbol( library, "thrdlib_yield" , true  );
-
-	lib_init( procs );
-}
-
-void thrdlib::clean( void ) {
-	if(lib_clean) lib_clean();
-}
+	//--------------------
+	// Basic kernel features
+	void init( int procs ) { thrdlib_init(procs); }
+	void clean( void ) { thrdlib_clean(); }
+};
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.hpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.hpp	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.hpp	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -6,13 +6,13 @@
 	//--------------------
 	// Basic thread support
-	extern thread_t (*create)( void (*main)( thread_t ) );
-	extern void (*join)( thread_t handle );
-	extern void (*park)( thread_t handle );
-	extern void (*unpark)( thread_t handle );
-	extern void (*yield)( void ) ;
+	extern thread_t create( void (*main)( thread_t ) );
+	extern void join( thread_t handle );
+	extern void park( thread_t handle );
+	extern void unpark( thread_t handle );
+	extern void yield( void ) ;
 
 	//--------------------
 	// Basic kernel features
-	extern void init( const char * name, int procs );
+	extern void init( int procs );
 	extern void clean( void );
 };
Index: libcfa/src/concurrency/coroutine.cfa
===================================================================
--- libcfa/src/concurrency/coroutine.cfa	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ libcfa/src/concurrency/coroutine.cfa	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -10,6 +10,6 @@
 // Created On       : Mon Nov 28 12:27:26 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Oct 23 23:05:24 2020
-// Update Count     : 22
+// Last Modified On : Tue Dec 15 12:06:04 2020
+// Update Count     : 23
 //
 
@@ -88,4 +88,5 @@
 static const size_t MinStackSize = 1000;
 extern size_t __page_size;				// architecture pagesize HACK, should go in proper runtime singleton
+extern int __map_prot;
 
 void __stack_prepare( __stack_info_t * this, size_t create_size );
@@ -206,5 +207,5 @@
 		__cfaabi_dbg_debug_do(
 			storage = (char*)(storage) - __page_size;
-			if ( mprotect( storage, __page_size, PROT_READ | PROT_WRITE ) == -1 ) {
+			if ( mprotect( storage, __page_size, __map_prot ) == -1 ) {
 				abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
 			}
Index: libcfa/src/concurrency/kernel/startup.cfa
===================================================================
--- libcfa/src/concurrency/kernel/startup.cfa	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ libcfa/src/concurrency/kernel/startup.cfa	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -117,5 +117,5 @@
 }
 
-size_t __page_size = 0;
+extern size_t __page_size;
 
 //-----------------------------------------------------------------------------
@@ -161,6 +161,4 @@
 	/* paranoid */ verify( ! __preemption_enabled() );
 	__cfadbg_print_safe(runtime_core, "Kernel : Starting\n");
-
-	__page_size = sysconf( _SC_PAGESIZE );
 
 	__cfa_dbg_global_clusters.list{ __get };
@@ -681,5 +679,5 @@
 	#if CFA_PROCESSOR_USE_MMAP
 		stacksize = ceiling( stacksize, __page_size ) + __page_size;
-		stack = mmap(0p, stacksize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+		stack = mmap(0p, stacksize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
 		if(stack == ((void*)-1)) {
 			abort( "pthread stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) );
Index: libcfa/src/heap.cfa
===================================================================
--- libcfa/src/heap.cfa	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ libcfa/src/heap.cfa	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -10,9 +10,10 @@
 // Created On       : Tue Dec 19 21:58:35 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Dec 13 22:04:10 2020
-// Update Count     : 984
+// Last Modified On : Tue Dec 15 21:37:54 2020
+// Update Count     : 1013
 //
 
 #include <unistd.h>										// sbrk, sysconf
+#include <stdlib.h>										// EXIT_FAILURE
 #include <stdbool.h>									// true, false
 #include <stdio.h>										// snprintf, fileno
@@ -71,5 +72,5 @@
 	// Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address,
 	// the brk address is extended by the extension amount.
-	__CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
+	__CFA_DEFAULT_HEAP_EXPANSION__ = (10 * 1024 * 1024),
 
 	// Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets;
@@ -115,5 +116,6 @@
 
 // statically allocated variables => zero filled.
-static size_t pageSize;									// architecture pagesize
+size_t __page_size;										// architecture pagesize
+int __map_prot;											// common mmap/mprotect protection
 static size_t heapExpand;								// sbrk advance
 static size_t mmapStart;								// cross over point for mmap
@@ -249,5 +251,5 @@
 #endif // FASTLOOKUP
 
-static int mmapFd = -1;									// fake or actual fd for anonymous file
+static const off_t mmapFd = -1;							// fake or actual fd for anonymous file
 #ifdef __CFA_DEBUG__
 static bool heapBoot = 0;								// detect recursion during boot
@@ -374,5 +376,5 @@
 
 static inline bool setMmapStart( size_t value ) {		// true => mmapped, false => sbrk
-  if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return false;
+  if ( value < __page_size || bucketSizes[NoBucketSizes - 1] < value ) return false;
 	mmapStart = value;									// set global
 
@@ -484,4 +486,5 @@
 #define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes."
 
+#include <unistd.h>
 static inline void * extend( size_t size ) with( heapManager ) {
 	lock( extlock __cfaabi_dbg_ctx2 );
@@ -490,15 +493,15 @@
 		// If the size requested is bigger than the current remaining storage, increase the size of the heap.
 
-		size_t increase = ceiling2( size > heapExpand ? size : heapExpand, pageSize );
+		size_t increase = ceiling2( size > heapExpand ? size : heapExpand, __page_size );
+		// Do not call abort or strerror( errno ) as they may call malloc.
 		if ( sbrk( increase ) == (void *)-1 ) {			// failed, no memory ?
 			unlock( extlock );
-			abort( NO_MEMORY_MSG, size );				// give up
-		} // if
-		if ( mprotect( (char *)heapEnd + heapRemaining, increase, PROT_READ | PROT_WRITE | PROT_EXEC ) ) {
-			enum { BufferSize = 128 };
-			char helpText[BufferSize];
-			// Do not call strerror( errno ) as it may call malloc.
-			int len = snprintf( helpText, BufferSize, "internal error, extend(), mprotect failure, heapEnd:%p size:%zd, errno:%d.", heapEnd, increase, errno );
-			__cfaabi_bits_write( STDERR_FILENO, helpText, len );
+			__cfaabi_bits_print_nolock( STDERR_FILENO, NO_MEMORY_MSG, size );
+			_exit( EXIT_FAILURE );
+		} // if
+		if ( mprotect( (char *)heapEnd + heapRemaining, increase, __map_prot ) ) {
+			unlock( extlock );
+			__cfaabi_bits_print_nolock( STDERR_FILENO, "extend() : internal error, mprotect failure, heapEnd:%p size:%zd, errno:%d.\n", heapEnd, increase, errno );
+			_exit( EXIT_FAILURE );
 		} // if
 		#ifdef __STATISTICS__
@@ -508,6 +511,6 @@
 		#ifdef __CFA_DEBUG__
 		// Set new memory to garbage so subsequent uninitialized usages might fail.
-		//memset( (char *)heapEnd + heapRemaining, '\377', increase );
-		Memset( (char *)heapEnd + heapRemaining, increase );
+		memset( (char *)heapEnd + heapRemaining, '\hde', increase );
+		//Memset( (char *)heapEnd + heapRemaining, increase );
 		#endif // __CFA_DEBUG__
 		rem = heapRemaining + increase - size;
@@ -568,6 +571,6 @@
 		block->header.kind.real.home = freeElem;		// pointer back to free list of apropriate size
 	} else {											// large size => mmap
-  if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p;
-		tsize = ceiling2( tsize, pageSize );			// must be multiple of page size
+  if ( unlikely( size > ULONG_MAX - __page_size ) ) return 0p;
+		tsize = ceiling2( tsize, __page_size );			// must be multiple of page size
 		#ifdef __STATISTICS__
 		__atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
@@ -575,5 +578,5 @@
 		#endif // __STATISTICS__
 
-		block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
+		block = (HeapManager.Storage *)mmap( 0, tsize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
 		if ( block == (HeapManager.Storage *)MAP_FAILED ) { // failed ?
 			if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory
@@ -583,6 +586,6 @@
 		#ifdef __CFA_DEBUG__
 		// Set new memory to garbage so subsequent uninitialized usages might fail.
-		//memset( block, '\377', tsize );
-		Memset( block, tsize );
+		memset( block, '\hde', tsize );
+		//Memset( block, tsize );
 		#endif // __CFA_DEBUG__
 		block->header.kind.real.blockSize = tsize;		// storage size for munmap
@@ -624,15 +627,13 @@
 		#endif // __STATISTICS__
 		if ( munmap( header, size ) == -1 ) {
-			#ifdef __CFA_DEBUG__
 			abort( "Attempt to deallocate storage %p not allocated or with corrupt header.\n"
 				   "Possible cause is invalid pointer.",
 				   addr );
-			#endif // __CFA_DEBUG__
 		} // if
 	} else {
 		#ifdef __CFA_DEBUG__
 		// Set free memory to garbage so subsequent usages might fail.
-		//memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );
-		Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) );
+		memset( ((HeapManager.Storage *)header)->data, '\hde', freeElem->blockSize - sizeof( HeapManager.Storage ) );
+		//Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) );
 		#endif // __CFA_DEBUG__
 
@@ -703,5 +704,6 @@
 
 static void ?{}( HeapManager & manager ) with( manager ) {
-	pageSize = sysconf( _SC_PAGESIZE );
+	__page_size = sysconf( _SC_PAGESIZE );
+	__map_prot = PROT_READ | PROT_WRITE | PROT_EXEC;
 
 	for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
@@ -723,5 +725,5 @@
 
 	char * end = (char *)sbrk( 0 );
-	heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, pageSize ) - end ); // move start of heap to multiple of alignment
+	heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, __page_size ) - end ); // move start of heap to multiple of alignment
 } // HeapManager
 
@@ -741,5 +743,4 @@
 	#ifdef __CFA_DEBUG__
 	if ( heapBoot ) {									// check for recursion during system boot
-		// DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
 		abort( "boot() : internal error, recursively invoked during system boot." );
 	} // if
@@ -1048,5 +1049,5 @@
 	// page size.  It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).
 	void * valloc( size_t size ) {
-		return memalign( pageSize, size );
+		return memalign( __page_size, size );
 	} // valloc
 
@@ -1054,5 +1055,5 @@
 	// Same as valloc but rounds size to multiple of page size.
 	void * pvalloc( size_t size ) {
-		return memalign( pageSize, ceiling2( size, pageSize ) );
+		return memalign( __page_size, ceiling2( size, __page_size ) );
 	} // pvalloc
 
@@ -1193,5 +1194,5 @@
 		choose( option ) {
 		  case M_TOP_PAD:
-			heapExpand = ceiling2( value, pageSize ); return 1;
+			heapExpand = ceiling2( value, __page_size ); return 1;
 		  case M_MMAP_THRESHOLD:
 			if ( setMmapStart( value ) ) return 1;
Index: tests/heap.cfa
===================================================================
--- tests/heap.cfa	(revision ccb8c8adf8b195fa78310c842465c1414b3c4ab2)
+++ tests/heap.cfa	(revision 42f6e07e6f562d26e2a4c552e12cfcd2f2660dce)
@@ -10,6 +10,6 @@
 // Created On       : Tue Nov  6 17:54:56 2018
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Sep 25 15:21:52 2020
-// Update Count     : 73
+// Last Modified On : Tue Dec 15 12:11:51 2020
+// Update Count     : 79
 // 
 
@@ -27,7 +27,10 @@
 // }
 
-#define __U_DEFAULT_MMAP_START__ (512 * 1024 + 1)
-size_t default_mmap_start() __attribute__(( weak )) {
-	return __U_DEFAULT_MMAP_START__;
+size_t default_heap_expansion() {
+	return 10 * 1024 * 1024;
+} // default_heap_expansion
+
+size_t default_mmap_start() {
+	return 512 * 1024 + 1;
 } // default_mmap_start
 
