Index: libcfa/src/concurrency/coroutine.cfa
===================================================================
--- libcfa/src/concurrency/coroutine.cfa	(revision 212c2187acc76b800c2bbe0c4524f610ab71dac8)
+++ libcfa/src/concurrency/coroutine.cfa	(revision b2f6113b6922a9164605cb05cd095dc177208621)
@@ -35,9 +35,9 @@
 
 extern "C" {
-      void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
-      static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__));
-      static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) {
-            abort();
-      }
+	void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
+	static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__));
+	static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) {
+		abort();
+	}
 }
 
@@ -47,57 +47,65 @@
 // minimum feasible stack size in bytes
 #define MinStackSize 1000
-static size_t pageSize = 0;				// architecture pagesize HACK, should go in proper runtime singleton
+extern size_t __page_size;				// architecture pagesize HACK, should go in proper runtime singleton
+
+void __stack_prepare( __stack_info_t * this, size_t create_size );
 
 //-----------------------------------------------------------------------------
 // Coroutine ctors and dtors
-void ?{}( coStack_t & this, void * storage, size_t storageSize ) with( this ) {
-      size		 = storageSize == 0 ? 65000 : storageSize; // size of stack
-      this.storage = storage;                                // pointer to stack
-      limit		 = NULL;                                   // stack grows towards stack limit
-      base		 = NULL;                                   // base of stack
-      context	 = NULL;                                   // address of cfa_context_t
-      top		 = NULL;                                   // address of top of storage
-      userStack	 = storage != NULL;
-}
-
-void ^?{}(coStack_t & this) {
-      if ( ! this.userStack && this.storage ) {
-            __cfaabi_dbg_debug_do(
-                  if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
-                        abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
-                  }
-            );
-            free( this.storage );
-      }
+void ?{}( __stack_info_t & this, void * storage, size_t storageSize ) {
+	this.storage   = (__stack_t *)storage;
+
+	// Did we get a piece of storage ?
+	if (this.storage || storageSize != 0) {
+		// We either got a piece of storage or the user asked for a specific size
+		// Immediately create the stack
+		// (This is slightly unintuitive that non-default sized coroutines create are eagerly created
+		// but it avoids that all coroutines carry an unnecessary size)
+		verify( storageSize != 0 );
+		__stack_prepare( &this, storageSize );
+	}
+}
+
+void ^?{}(__stack_info_t & this) {
+	if ( ! this.userStack && this.storage ) {
+		void * storage = (char*)(this.storage) - this.storage->size;
+		__cfaabi_dbg_debug_do(
+			storage = (char*)(storage) - __page_size;
+			if ( mprotect( storage, __page_size, PROT_READ | PROT_WRITE ) == -1 ) {
+				abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
+			}
+		);
+		__cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage);
+		free( storage );
+	}
 }
 
 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {
-      (this.stack){storage, storageSize};
-      this.name = name;
-      errno_ = 0;
-      state = Start;
-      starter = NULL;
-      last = NULL;
-      cancellation = NULL;
+	(this.stack){storage, storageSize};
+	this.name = name;
+	state = Start;
+	starter = NULL;
+	last = NULL;
+	cancellation = NULL;
 }
 
 void ^?{}(coroutine_desc& this) {
-      if(this.state != Halted && this.state != Start) {
-            coroutine_desc * src = TL_GET( this_thread )->curr_cor;
-            coroutine_desc * dst = &this;
-
-            struct _Unwind_Exception storage;
-            storage.exception_class = -1;
-            storage.exception_cleanup = _CtxCoroutine_UnwindCleanup;
-            this.cancellation = &storage;
-            this.last = src;
-
-	      // not resuming self ?
-	      if ( src == dst ) {
-		      abort( "Attempt by coroutine %.256s (%p) to terminate itself.\n", src->name, src );
-            }
-
-	      CoroutineCtxSwitch( src, dst );
-      }
+	if(this.state != Halted && this.state != Start) {
+		coroutine_desc * src = TL_GET( this_thread )->curr_cor;
+		coroutine_desc * dst = &this;
+
+		struct _Unwind_Exception storage;
+		storage.exception_class = -1;
+		storage.exception_cleanup = _CtxCoroutine_UnwindCleanup;
+		this.cancellation = &storage;
+		this.last = src;
+
+		// not resuming self ?
+		if ( src == dst ) {
+			abort( "Attempt by coroutine %.256s (%p) to terminate itself.\n", src->name, src );
+		}
+
+		CoroutineCtxSwitch( src, dst );
+	}
 }
 
@@ -106,87 +114,91 @@
 forall(dtype T | is_coroutine(T))
 void prime(T& cor) {
-      coroutine_desc* this = get_coroutine(cor);
-      assert(this->state == Start);
-
-      this->state = Primed;
-      resume(cor);
+	coroutine_desc* this = get_coroutine(cor);
+	assert(this->state == Start);
+
+	this->state = Primed;
+	resume(cor);
 }
 
 // Wrapper for co
 void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
-      // Safety note : Preemption must be disabled since there is a race condition
-      // kernelTLS.this_thread->curr_cor and $rsp/$rbp must agree at all times
-      verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
-      disable_interrupts();
-
-      // set state of current coroutine to inactive
-      src->state = src->state == Halted ? Halted : Inactive;
-
-      // set new coroutine that task is executing
-      TL_GET( this_thread )->curr_cor = dst;
-
-      // context switch to specified coroutine
-      assert( src->stack.context );
-      CtxSwitch( src->stack.context, dst->stack.context );
-      // when CtxSwitch returns we are back in the src coroutine
-
-      // set state of new coroutine to active
-      src->state = Active;
-
-      enable_interrupts( __cfaabi_dbg_ctx );
-      verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
-
-
-      if( unlikely(src->cancellation != NULL) ) {
-            _CtxCoroutine_Unwind(src->cancellation, src);
-      }
-} //ctxSwitchDirect
-
-void create_stack( coStack_t* this, unsigned int storageSize ) with( *this ) {
-      //TEMP HACK do this on proper kernel startup
-      if(pageSize == 0ul) pageSize = sysconf( _SC_PAGESIZE );
-
-      size_t cxtSize = libCeiling( sizeof(machine_context_t), 8 ); // minimum alignment
-
-      if ( !storage ) {
-            __cfaabi_dbg_print_safe("Kernel : Creating stack of size %zu for stack obj %p\n", cxtSize + size + 8, this);
-
-            userStack = false;
-            size = libCeiling( storageSize, 16 );
-            // use malloc/memalign because "new" raises an exception for out-of-memory
-
-            // assume malloc has 8 byte alignment so add 8 to allow rounding up to 16 byte alignment
-            __cfaabi_dbg_debug_do( storage = memalign( pageSize, cxtSize + size + pageSize ) );
-            __cfaabi_dbg_no_debug_do( storage = malloc( cxtSize + size + 8 ) );
-
-            __cfaabi_dbg_debug_do(
-                  if ( mprotect( storage, pageSize, PROT_NONE ) == -1 ) {
-                        abort( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) );
-                  } // if
-            );
-
-            if ( (intptr_t)storage == 0 ) {
-                  abort( "Attempt to allocate %zd bytes of storage for coroutine or task execution-state but insufficient memory available.", size );
-            } // if
-
-            __cfaabi_dbg_debug_do( limit = (char *)storage + pageSize );
-            __cfaabi_dbg_no_debug_do( limit = (char *)libCeiling( (unsigned long)storage, 16 ) ); // minimum alignment
-
-      } else {
-            __cfaabi_dbg_print_safe("Kernel : stack obj %p using user stack %p(%u bytes)\n", this, storage, storageSize);
-
-            assertf( ((size_t)storage & (libAlign() - 1)) == 0ul, "Stack storage %p for task/coroutine must be aligned on %d byte boundary.", storage, (int)libAlign() );
-            userStack = true;
-            size = storageSize - cxtSize;
-
-            if ( size % 16 != 0u ) size -= 8;
-
-            limit = (char *)libCeiling( (unsigned long)storage, 16 ); // minimum alignment
-      } // if
-      assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
-
-      base = (char *)limit + size;
-      context = base;
-      top = (char *)context + cxtSize;
+	// Safety note : Preemption must be disabled since there is a race condition
+	// kernelTLS.this_thread->curr_cor and $rsp/$rbp must agree at all times
+	verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
+	disable_interrupts();
+
+	// set state of current coroutine to inactive
+	src->state = src->state == Halted ? Halted : Inactive;
+
+	// set new coroutine that task is executing
+	TL_GET( this_thread )->curr_cor = dst;
+
+	// context switch to specified coroutine
+	CtxSwitch( &src->context, &dst->context );
+	// when CtxSwitch returns we are back in the src coroutine
+
+	// set state of new coroutine to active
+	src->state = Active;
+
+	enable_interrupts( __cfaabi_dbg_ctx );
+	verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
+
+	if( unlikely(src->cancellation != NULL) ) {
+		_CtxCoroutine_Unwind(src->cancellation, src);
+	}
+}
+
+[void *, size_t] __stack_alloc( size_t storageSize ) {
+	static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
+	assert(__page_size != 0l);
+	size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
+
+	// If we are running debug, we also need to allocate a guardpage to catch stack overflows.
+	void * storage;
+	__cfaabi_dbg_debug_do(
+		storage = memalign( __page_size, size + __page_size );
+	);
+	__cfaabi_dbg_no_debug_do(
+		storage = (void*)malloc(size);
+	);
+
+	__cfaabi_dbg_print_safe("Kernel : Created stack %p of size %zu\n", storage, size);
+	__cfaabi_dbg_debug_do(
+		if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
+			abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );
+		}
+		storage = (void *)(((intptr_t)storage) + __page_size);
+	);
+
+	verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul );
+	return [storage, size];
+}
+
+void __stack_prepare( __stack_info_t * this, size_t create_size ) {
+	static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
+	bool userStack;
+	void * storage;
+	size_t size;
+	if ( !this->storage ) {
+		userStack = false;
+		[storage, size] = __stack_alloc( create_size );
+	} else {
+		userStack = true;
+		__cfaabi_dbg_print_safe("Kernel : stack obj %p using user stack %p(%zu bytes)\n", this, this->storage, this->storage->size);
+
+		// The stack must be aligned, advance the pointer to the next align data
+		storage = (void*)libCeiling( (intptr_t)this->storage, libAlign());
+
+		// The size needs to be shrinked to fit all the extra data structure and be aligned
+		ptrdiff_t diff = (intptr_t)storage - (intptr_t)this->storage;
+		size = libFloor(create_size - stack_data_size - diff, libAlign());
+	} // if
+	assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
+
+	this->storage = (__stack_t *)((intptr_t)storage + size);
+	this->storage->size  = size;
+	this->storage->limit = storage;
+	this->storage->base  = (void*)((intptr_t)storage + size);
+	this->userStack = userStack;
 }
 
@@ -194,24 +206,24 @@
 // is not inline (We can't inline Cforall in C)
 extern "C" {
-      void __suspend_internal(void) {
-            suspend();
-      }
-
-      void __leave_coroutine( coroutine_desc * src ) {
-            coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter;
-
-            src->state = Halted;
-
-            assertf( starter != 0,
-                  "Attempt to suspend/leave coroutine \"%.256s\" (%p) that has never been resumed.\n"
-                  "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
-                  src->name, src );
-            assertf( starter->state != Halted,
-                  "Attempt by coroutine \"%.256s\" (%p) to suspend/leave back to terminated coroutine \"%.256s\" (%p).\n"
-                  "Possible cause is terminated coroutine's main routine has already returned.",
-                  src->name, src, starter->name, starter );
-
-            CoroutineCtxSwitch( src, starter );
-      }
+	void __suspend_internal(void) {
+		suspend();
+	}
+
+	void __leave_coroutine( coroutine_desc * src ) {
+		coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter;
+
+		src->state = Halted;
+
+		assertf( starter != 0,
+			"Attempt to suspend/leave coroutine \"%.256s\" (%p) that has never been resumed.\n"
+			"Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
+			src->name, src );
+		assertf( starter->state != Halted,
+			"Attempt by coroutine \"%.256s\" (%p) to suspend/leave back to terminated coroutine \"%.256s\" (%p).\n"
+			"Possible cause is terminated coroutine's main routine has already returned.",
+			src->name, src, starter->name, starter );
+
+		CoroutineCtxSwitch( src, starter );
+	}
 }
 
