$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80423 - in trunk: boost/context boost/context/detail libs/context/build libs/context/doc libs/context/example libs/context/performance libs/context/src libs/context/src/asm libs/context/test
From: oliver.kowalke_at_[hidden]
Date: 2012-09-06 15:43:10
Author: olli
Date: 2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
New Revision: 80423
URL: http://svn.boost.org/trac/boost/changeset/80423
Log:
context: return pointer to fcontext_t
 - make_fcontext() allocated fcontext_t on context stack and return pointer
 - stack_allocator renamed to guarded_stack_allocator
 - simple_stack_allocator using calloc()/free() added
 - pagesize() made public accessible
Added:
   trunk/boost/context/guarded_stack_allocator.hpp   (contents, props changed)
   trunk/boost/context/simple_stack_allocator.hpp   (contents, props changed)
   trunk/boost/context/utils.hpp   (contents, props changed)
   trunk/libs/context/src/guarded_stack_allocator_posix.cpp   (contents, props changed)
   trunk/libs/context/src/guarded_stack_allocator_windows.cpp   (contents, props changed)
   trunk/libs/context/src/utils_posix.cpp   (contents, props changed)
   trunk/libs/context/src/utils_windows.cpp   (contents, props changed)
Removed:
   trunk/boost/context/stack_allocator.hpp
   trunk/libs/context/src/stack_allocator_posix.cpp
   trunk/libs/context/src/stack_allocator_windows.cpp
Text files modified: 
   trunk/boost/context/all.hpp                                 |     4                                         
   trunk/boost/context/detail/fcontext_i386.hpp                |    24 ++----                                  
   trunk/boost/context/detail/fcontext_mips.hpp                |     2                                         
   trunk/boost/context/fcontext.hpp                            |     2                                         
   trunk/libs/context/build/Jamfile.v2                         |     6 +                                       
   trunk/libs/context/doc/fcontext.qbk                         |    87 ++++++++++++------------                
   trunk/libs/context/doc/rationale.qbk                        |    15 +--                                     
   trunk/libs/context/doc/reference.qbk                        |    14 ++--                                    
   trunk/libs/context/doc/stack.qbk                            |    83 +++++++++++++++++++++--                 
   trunk/libs/context/doc/todo.qbk                             |     2                                         
   trunk/libs/context/example/exit.cpp                         |    29 ++++----                                
   trunk/libs/context/example/jump.cpp                         |    40 ++++++----                              
   trunk/libs/context/example/transfer.cpp                     |    19 ++--                                    
   trunk/libs/context/performance/performance.cpp              |    40 ++++++-----                             
   trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S     |    18 ++--                                    
   trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm     |    37 +++++-----                              
   trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S     |    30 ++++----                                
   trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S   |    25 +++---                                  
   trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S    |   138 ++++++++++++++++++++------------------- 
   trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S    |    32 +++++----                               
   trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S    |    30 ++++---                                 
   trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm   |    90 +++++++++++++------------               
   trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S   |    36 +++++----                               
   trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S |    36 +++++----                               
   trunk/libs/context/test/test_context.cpp                    |   124 ++++++++++++++++++++---------------     
   25 files changed, 535 insertions(+), 428 deletions(-)
Modified: trunk/boost/context/all.hpp
==============================================================================
--- trunk/boost/context/all.hpp	(original)
+++ trunk/boost/context/all.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -8,6 +8,8 @@
 #define BOOST_CTX_ALL_H
 
 #include <boost/context/fcontext.hpp>
-#include <boost/context/stack_allocator.hpp>
+#include <boost/context/guarded_stack_allocator.hpp>
+#include <boost/context/simple_stack_allocator.hpp>
+#include <boost/context/utils.hpp>
 
 #endif // BOOST_CTX_ALL_H
Modified: trunk/boost/context/detail/fcontext_i386.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_i386.hpp	(original)
+++ trunk/boost/context/detail/fcontext_i386.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -27,33 +27,25 @@
 
 struct stack_t
 {
-    void    *   sp;
-    std::size_t size;
+    boost::uint32_t     code;
+    void            *   sp;
+    std::size_t         size;
 
     stack_t() :
-        sp( 0), size( 0)
-    {}
-};
-
-struct fp_t
-{
-    boost::uint32_t     fc_freg[2];
-
-    fp_t() :
-        fc_freg()
+        code( 0), sp( 0), size( 0)
     {}
 };
 
 struct fcontext_t
 {
-    boost::uint32_t     fc_greg[6];
     stack_t             fc_stack;
-    fp_t                fc_fp;
+    boost::uint32_t     fc_greg[6];
+    boost::uint32_t     fc_freg[2];
 
     fcontext_t() :
-        fc_greg(),
         fc_stack(),
-        fc_fp()
+        fc_greg(),
+        fc_freg()
     {}
 };
 
Modified: trunk/boost/context/detail/fcontext_mips.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_mips.hpp	(original)
+++ trunk/boost/context/detail/fcontext_mips.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -48,7 +48,7 @@
 
 struct fcontext_t
 {
-    boost::uint64_t     fc_greg[13];
+    boost::uint32_t     fc_greg[12];
     stack_t             fc_stack;
     fp_t                fc_fp;
 
Modified: trunk/boost/context/fcontext.hpp
==============================================================================
--- trunk/boost/context/fcontext.hpp	(original)
+++ trunk/boost/context/fcontext.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -70,7 +70,7 @@
 extern "C" BOOST_CONTEXT_DECL
 intptr_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t * ofc, fcontext_t const* nfc, intptr_t vp, bool preserve_fpu = true);
 extern "C" BOOST_CONTEXT_DECL
-void BOOST_CONTEXT_CALLDECL make_fcontext( fcontext_t * fc, void (* fn)( intptr_t) );
+fcontext_t * BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) );
 
 }}
 
Added: trunk/boost/context/guarded_stack_allocator.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/context/guarded_stack_allocator.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -0,0 +1,55 @@
+
+//          Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CTX_GUARDED_STACK_ALLOCATOR_H
+#define BOOST_CTX_GUARDED_STACK_ALLOCATOR_H
+
+#include <boost/config.hpp>
+
+#if ! defined (BOOST_WINDOWS)
+extern "C" {
+#include <unistd.h>
+}
+#endif
+
+#if defined (BOOST_WINDOWS) || _POSIX_C_SOURCE >= 200112L
+
+#include <cstddef>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace ctx {
+
+class BOOST_CONTEXT_DECL guarded_stack_allocator
+{
+public:
+    static bool is_stack_unbound();
+
+    static std::size_t default_stacksize();
+
+    static std::size_t minimum_stacksize();
+
+    static std::size_t maximum_stacksize();
+
+    void * allocate( std::size_t) const;
+
+    void deallocate( void *, std::size_t) const;
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_SUFFIX
+#endif
+
+#endif
+
+#endif // BOOST_CTX_GUARDED_STACK_ALLOCATOR_H
Added: trunk/boost/context/simple_stack_allocator.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/context/simple_stack_allocator.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -0,0 +1,67 @@
+
+//          Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CTX_SIMPLE_STACK_ALLOCATOR_H
+#define BOOST_CTX_SIMPLE_STACK_ALLOCATOR_H
+
+#include <cstddef>
+#include <cstdlib>
+#include <stdexcept>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace ctx {
+
+template< std::size_t Max, std::size_t Default, std::size_t Min >
+class simple_stack_allocator
+{
+public:
+    static std::size_t maximum_stacksize()
+    { return Max; }
+
+    static std::size_t default_stacksize()
+    { return Default; }
+
+    static std::size_t minimum_stacksize()
+    { return Min; }
+
+    void * allocate( std::size_t size) const
+    {
+        BOOST_ASSERT( minimum_stacksize() <= size);
+        BOOST_ASSERT( maximum_stacksize() >= size);
+   
+        void * limit = std::calloc( size, sizeof( char) );
+        if ( ! limit) throw std::bad_alloc();
+
+        return static_cast< char * >( limit) + size;
+    }
+
+    void deallocate( void * vp, std::size_t size) const
+    {
+        BOOST_ASSERT( vp);
+        BOOST_ASSERT( minimum_stacksize() <= size);
+        BOOST_ASSERT( maximum_stacksize() >= size);
+
+        void * limit = static_cast< char * >( vp) - size;
+        std::free( limit);
+    }
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_CTX_SIMPLE_STACK_ALLOCATOR_H
Deleted: trunk/boost/context/stack_allocator.hpp
==============================================================================
--- trunk/boost/context/stack_allocator.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
+++ (empty file)
@@ -1,45 +0,0 @@
-
-//          Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-//    (See accompanying file LICENSE_1_0.txt or copy at
-//          http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_CTX_STACK_ALLOCATOR_H
-#define BOOST_CTX_STACK_ALLOCATOR_H
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-
-#include <boost/context/detail/config.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-#  include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace ctx {
-
-class BOOST_CONTEXT_DECL stack_allocator
-{
-public:
-    static bool is_stack_unbound();
-
-    static std::size_t default_stacksize();
-
-    static std::size_t minimum_stacksize();
-
-    static std::size_t maximum_stacksize();
-
-    void * allocate( std::size_t) const;
-
-    void deallocate( void *, std::size_t) const;
-};
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-#  include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CTX_STACK_ALLOCATOR_H
Added: trunk/boost/context/utils.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/context/utils.hpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -0,0 +1,41 @@
+
+//          Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CTX_UTILS_H
+#define BOOST_CTX_UTILS_H
+
+#include <boost/config.hpp>
+
+#if ! defined (BOOST_WINDOWS)
+extern "C" {
+#include <unistd.h>
+}
+#endif
+
+#if defined (BOOST_WINDOWS) || _POSIX_C_SOURCE >= 200112L
+
+#include <cstddef>
+
+#include <boost/context/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace ctx {
+
+BOOST_CONTEXT_DECL std::size_t pagesize();
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_SUFFIX
+#endif
+
+#endif
+
+#endif // BOOST_CTX_UTILS_H
Modified: trunk/libs/context/build/Jamfile.v2
==============================================================================
--- trunk/libs/context/build/Jamfile.v2	(original)
+++ trunk/libs/context/build/Jamfile.v2	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -407,13 +407,15 @@
 alias context_sources
    : fcontext.cpp
      seh.cpp
-     stack_allocator_windows.cpp
+     guarded_stack_allocator_windows.cpp
+     utils_windows.cpp
    : <target-os>windows
    ;
 
 alias context_sources
    : fcontext.cpp
-     stack_allocator_posix.cpp
+     guarded_stack_allocator_posix.cpp
+     utils_posix.cpp
    ;
 
 explicit context_sources ;
Modified: trunk/libs/context/doc/fcontext.qbk
==============================================================================
--- trunk/libs/context/doc/fcontext.qbk	(original)
+++ trunk/libs/context/doc/fcontext.qbk	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -19,30 +19,30 @@
 [warning If __fcontext__ is used in a multithreaded application, it can migrated
 between threads, but must not reference __tls__.]
 
+[important The low level API is the part to port to new platforms.]
+
 [note If __fls__ is used on Windows, the user is responsible for calling 
 __fls_alloc__, __fls_free__.]
 
-[important The low level API is the part to port to new platforms.]
-
 
 [heading Executing a context]
 
 A new context supposed to execute a __context_fn__ (returning void and accepting
-intptr_t as argument) must be initialized by function __make_fcontext__.
+intptr_t as argument) will be created on top of the stack (at 16 byte boundary)
+by function __make_fcontext__.
 
             // context-function
             void f( intptr);
 
             // creates and manages a protected stack (with guard page)
-            ctx::stack_allocator alloc;
-            fc.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
-            fc.fc_stack.size = ctx::minimum_stacksize();
+            ctx::guarded_stack_allocator alloc;
+            void * sp( alloc.allocate(ctx::minimum_stacksize()));
+            std::size_t size( ctx::guarded_stack_allocator::minimum_stacksize());
 
             // context fc uses f() as context function
-            make_fcontext( & fc, f);
-
-__fcontext__ requires a pointer (__fc_base__) as well as the size of the
-stack.
+            // fcontext_t is placed on top of context stack
+            // a pointer to fcontext_t is returned
+            fcontext_t  * fc( make_fcontext( sp, size, f));
 
 Calling __jump_fcontext__ invokes the __context_fn__ in a newly created context
 complete with registers, flags, stack and instruction pointers.  When control
@@ -54,39 +54,36 @@
 
         namespace ctx = boost::ctx;
 
-        ctx::fcontext_t fcm, fc1, fc2;
+        ctx::fcontext_t fcm, * fc1, * fc2;
 
         void f1( intptr_t)
         {
                 std::cout << "f1: entered" << std::endl;
-                std::cout << "f1: call jump_fcontext( & fc1, & fc2, 0)" << std::endl;
-                ctx::jump_fcontext( & fc1, & fc2, 0);
+                std::cout << "f1: call jump_fcontext( fc1, fc2, 0)" << std::endl;
+                ctx::jump_fcontext( fc1, fc2, 0);
                 std::cout << "f1: return" << std::endl;
-                ctx::jump_fcontext( & fc1, & fcm, 0);
+                ctx::jump_fcontext( fc1, & fcm, 0);
         }
 
         void f2( intptr_t)
         {
                 std::cout << "f2: entered" << std::endl;
-                std::cout << "f2: call jump_fcontext( & fc2, & fc1, 0)" << std::endl;
-                ctx::jump_fcontext( & fc2, & fc1, 0);
+                std::cout << "f2: call jump_fcontext( fc2, fc1, 0)" << std::endl;
+                ctx::jump_fcontext( fc2, fc1, 0);
                 BOOST_ASSERT( false && ! "f2: never returns");
         }
 
         int main( int argc, char * argv[])
         {
-                ctx::stack_allocator alloc1, alloc2;
+                ctx::guarded_stack_allocator alloc;
+                void * sp1( alloc.allocate(ctx::minimum_stacksize()));
+                std::size_t size( ctx::guarded_stack_allocator::minimum_stacksize());
 
-                fc1.fc_stack.sp = alloc1.allocate(ctx::minimum_stacksize());
-                fc1.fc_stack.size = ctx::minimum_stacksize();
-                ctx::make_fcontext( & fc1, f1);
-
-                fc2.fc_stack.sp = alloc2.allocate(ctx::minimum_stacksize());
-                fc2.fc_stack.size = ctx::minimum_stacksize();
-                ctx::make_fcontext( & fc2, f2);
+                fc1 = ctx::make_fcontext( sp1, size, f1);
+                fc2 = ctx::make_fcontext( sp2, size, f2);
 
-                std::cout << "main: call jump_fcontext( & fcm, & fc1, 0)" << std::endl;
-                ctx::jump_fcontext( & fcm, & fc1, 0);
+                std::cout << "main: call jump_fcontext( & fcm, fc1, 0)" << std::endl;
+                ctx::jump_fcontext( & fcm, fc1, 0);
 
                 std::cout << "main: done" << std::endl;
 
@@ -111,6 +108,8 @@
 [warning Calling __jump_fcontext__ to the same context from inside the same
 context results in undefined behaviour.]
 
+[important The size of the stack is required to be larger than the size of fcontext_t.]
+
 [note In contrast to threads, which are preemtive, __fcontext__ switches are
 cooperative (programmer controls when switch will happen). The kernel is not
 involved in the context switches.]
@@ -127,34 +126,33 @@
 
         namespace ctx = boost::ctx;
 
-        ctx::fcontext_t fc1, fcm;
+        ctx::fcontext_t fcm, * fc;
 
         typedef std::pair< int, int >   pair_t;
 
-        void f1( intptr_t param)
+        void f( intptr_t param)
         {
             pair_t * p = ( pair_t *) param;
 
-            p = ( pair_t *) ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
+            p = ( pair_t *) ctx::jump_fcontext( fc, & fcm, ( intptr_t) ( p->first + p->second) );
 
-            ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
+            ctx::jump_fcontext( fc, & fcm, ( intptr_t) ( p->first + p->second) );
         }
 
         int main( int argc, char * argv[])
         {
-            ctx::stack_allocator alloc;
+            ctx::guarded_stack_allocator alloc;
+            void * sp( alloc.allocate(ctx::minimum_stacksize()));
+            std::size_t size( ctx::guarded_stack_allocator::minimum_stacksize());
 
-            fc1.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
-            fc1.fc_stack.size = ctx::minimum_stacksize();
-            fc1.fc_link = & fcm;
             pair_t p( std::make_pair( 2, 7) );
-            ctx::make_fcontext( & fc1, f1);
+            fc = ctx::make_fcontext( sp, size, f);
 
-            int res = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & p);
+            int res = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & p);
             std::cout << p.first << " + " << p.second << " == " << res << std::endl;
 
             p = std::make_pair( 5, 6);
-            res = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & p);
+            res = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & p);
             std::cout << p.first << " + " << p.second << " == " << res << std::endl;
 
             std::cout << "main: done" << std::endl;
@@ -206,8 +204,8 @@
             stack_t  fc_stack;
         };
 
-        intptr_t jump_fcontext( fcontext_t * ofc, fcontext_t const* nfc, intptr_t vp);
-        void make_fcontext( fcontext_t * fc, void(* fn)(intptr_t) );
+        intptr_t jump_fcontext( fcontext_t * ofc, fcontext_t const* nfc, intptr_t vp, bool preserve_fpu = true);
+        fcontext_t * make_fcontext( void * sp, std::size_t size, void(* fn)(intptr_t) );
 
 [heading `sp`]
 [variablelist
@@ -225,7 +223,7 @@
 [[Member:] [Tracks the memory for the context's stack.]]
 ]
 
-[heading `intptr_t jump_fcontext( fcontext_t * ofc, fcontext_t * nfc, intptr_t p, bool preserve_fpu)`]
+[heading `intptr_t jump_fcontext( fcontext_t * ofc, fcontext_t * nfc, intptr_t p, bool preserve_fpu = true)`]
 [variablelist
 [[Effects:] [Stores the current context data (stack pointer, instruction
 pointer, and CPU registers) to `*ofc` and restores the context data from `*nfc`,
@@ -237,11 +235,12 @@
 `jump_fcontext()`, if any.]]
 ]
 
-[heading `void make_fcontext( fcontext_t * fc, void(*fn)(intptr_t))`]
+[heading `fcontext_t * make_fcontext( void * sp, std::size_t size, void(*fn)(intptr_t))`]
 [variablelist
-[[Precondition:] [A stack is applied to `*fc` before `make_fcontext()` is called.]]
-[[Effects:] [Modifies `*fc` in order to execute `fn` when the context is
-activated next.]]
+[[Precondition:] [Stack `sp` function pointer `fn` are valid and `size` > 0.]]
+[[Effects:] [Creates an fcontext_t at the beginning of the stack and prepares the stack
+to execute the __context_fn__ `fn`.]]
+[[Returns:][Returns a pointer to fcontext_t which is placed on the stack.]]
 ]
 
 [endsect]
Modified: trunk/libs/context/doc/rationale.qbk
==============================================================================
--- trunk/libs/context/doc/rationale.qbk	(original)
+++ trunk/libs/context/doc/rationale.qbk	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -48,8 +48,7 @@
 C99 defines `setjmp()`/`longjmp()` to provide non-local jumps but it does not
 require that ['longjmp()] preserves the current stack frame. Therefore, jumping
 into a function which was exited via a call to ['longjmp()] is undefined
-[footnote [@boost:/libs/context/doc/pdf/iso_c99.pdf ISO/IEC 9899:1999, 2005],
-7.13.2.1:2].
+[footnote ISO/IEC 9899:1999, 2005, 7.13.2.1:2].
 
 
 [heading ucontext_t]
@@ -62,8 +61,7 @@
 The third argument of `makecontext()` specifies the number of integer arguments
 that follow which will require function pointer cast if `func` will accept those
 arguments which is undefined in C99
-[footnote [@boost:/libs/context/doc/pdf/iso_c99.pdf ISO/IEC 9899:1999, 2005],
-J.2].
+[footnote ISO/IEC 9899:1999, 2005, J.2].
 
 The arguments in the var-arg list are required to be integers, passing pointers
 in var-arg list is not guarantied to work, especially it will fail for
@@ -105,8 +103,7 @@
 
 "The FpCsr and the MxCsr register must be saved and restored before any call or return
 by any procedure that needs to modify them ..."
-[footnote [@boost:/libs/context/doc/pdf/calling-conventions.pdf 'Calling Conventions',
-Agner Fog]].
+[footnote 'Calling Conventions', Agner Fog].
 
 
 [heading x86_64]
@@ -131,8 +128,7 @@
 'Legacy Floating-Point Support']].
 
 "The 64-bit Microsoft compiler does not use ST(0)-ST(7)/MM0-MM7".
-[footnote [@boost:/libs/context/doc/pdf/calling-conventions.pdf 'Calling Conventions',
-Agner Fog]].
+[footnote 'Calling Conventions', Agner Fog].
 
 "XMM6-XMM15 must be preserved"
 [footnote [@http://msdn.microsoft.com/en-us/library/9z1stfyw%28v=vs.100%29.aspx MSDN
@@ -144,8 +140,7 @@
 "The control bits of the MxCsr register are callee-saved (preserved across calls),
 while the status bits are caller-saved (not preserved). The x87 status word register is
 caller-saved, whereas the x87 control word (FpCsr) is callee-saved."
-[footnote [@boost:/libs/context/doc/pdf/x86_64-sysv.pdf SysV ABI AMD64 Architecture
-Processor Supplement Draft Version 0.99.4, 3.2.1]].
+[footnote SysV ABI AMD64 Architecture Processor Supplement Draft Version 0.99.4, 3.2.1].
 
 [endsect]
 
Modified: trunk/libs/context/doc/reference.qbk
==============================================================================
--- trunk/libs/context/doc/reference.qbk	(original)
+++ trunk/libs/context/doc/reference.qbk	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -9,34 +9,34 @@
 
 [heading ARM]
 
-* AAPCS ABI: [@boost:/libs/context/doc/pdf/arm-aapcs.pdf Procedure Call Standard for the ARM Architecture]
-* AAPCS/LINUX: [@boost:/libs/context/doc/pdf/arm-linux-aapcs.pdf ARM GNU/Linux Application Binary Interface Supplement]
+* AAPCS ABI: Procedure Call Standard for the ARM Architecture
+* AAPCS/LINUX: ARM GNU/Linux Application Binary Interface Supplement
 
 
 [heading MIPS]
 
-* O32 ABI: [@boost:/libs/context/doc/pdf/mips-o32.pdf SYSTEM V APPLICATION BINARY INTERFACE, MIPS RISC Processor Supplement]
+* O32 ABI: SYSTEM V APPLICATION BINARY INTERFACE, MIPS RISC Processor Supplement
 
 
 [heading PowerPC32]
 
-* SYSV ABI: [@boost:/libs/context/doc/pdf/ppc32-sysv.pdf SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement]
+* SYSV ABI: SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement
 
 
 [heading PowerPC64]
 
-* SYSV ABI: [@boost:/libs/context/doc/pdf/ppc64-sysv.pdf PowerPC User Instruction Set Architecture, Book I]
+* SYSV ABI: PowerPC User Instruction Set Architecture, Book I
 
 
 [heading X86-32]
 
-* SYSV ABI: [@boost:/libs/context/doc/pdf/x86_32-sysv.pdf SYSTEM V APPLICATION BINARY INTERFACE, Intel386TM Architecture Processor Supplement]
+* SYSV ABI: SYSTEM V APPLICATION BINARY INTERFACE, Intel386TM Architecture Processor Supplement
 * MS PE: [@http://msdn.microsoft.com/en-us/library/k2b2ssfy.aspx Calling Conventions]
 
 
 [heading X86-64]
 
-* SYSV ABI: [@boost:/libs/context/doc/pdf/x86_64-sysv.pdf System V Application Binary Interface, AMD64 Architecture Processor Supplement]
+* SYSV ABI: System V Application Binary Interface, AMD64 Architecture Processor Supplement
 * MS PE: [@http://msdn.microsoft.com/en-us/library/7kcdt6fy%28VS.80%29.aspx x64 Software Conventions]
 
 
Modified: trunk/libs/context/doc/stack.qbk
==============================================================================
--- trunk/libs/context/doc/stack.qbk	(original)
+++ trunk/libs/context/doc/stack.qbk	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -47,15 +47,18 @@
 upwards).]
 
 
-[section:stack_allocator Class `stack_allocator`]
+[section:guarded_stack_allocator Class `guarded_stack_allocator`]
 
-__boost_context__ provides the default implementation `stack_allocator` which models
+__boost_context__ provides the class `guarded_stack_allocator` which models
 the __stack_allocator_concept__ concept.
-It appends a __guard_page__ at the end of the stack to protect against exceeding
+It appends a __guard_page__ at the end of each stack to protect against exceeding
 the stack. If the guard page is accessed (read or write operation) a
 segmentation fault/access violation is generated by the operating system.
 
-        class stack_allocator
+[note The appended `guard page` is [*not] mapped to pyhsical memory, only
+virtual addresses are used.]
+
+        class guarded_stack_allocator
         {
             static bool is_stack_unbound();
 
@@ -73,14 +76,12 @@
 [heading `static bool is_stack_unbound()`]
 [variablelist
 [[Returns:] [Returns `true` if the environment defines no limit for the size of a stack.]]
-[[Throws:] [Nothing.]]
 ]
 
 [heading `static std::size_t maximum_stacksize()`]
 [variablelist
 [[Preconditions:] [`is_stack_unbound()` returns `false`.]]
 [[Returns:] [Returns the maximum size in bytes of stack defined by the environment.]]
-[[Throws:] [Nothing.]]
 ]
 
 [heading `static std::size_t default_stacksize()`]
@@ -93,8 +94,7 @@
 [heading `static std::size_t minimum_stacksize()`]
 [variablelist
 [[Returns:] [Returns the minimum size in bytes of stack defined by the
-environment (Windows 4kB, defined by rlimit on POSIX).]]
-[[Throws:] [Nothing.]]
+environment (Win32 4kB/Win64 8kB, defined by rlimit on POSIX).]]
 ]
 
 [heading `void * allocate( std::size_t size)`]
@@ -106,13 +106,76 @@
 [[Returns:] [Returns pointer to the start address of the new stack. Depending
 on the architecture the stack grows downwards/upwards the returned address is
 the highest/lowest address of the stack.]]
-[[Throws:] [std::invalid_argument if pre-conditions violated.]]
 ]
 
 [heading `void deallocate( void * sp, std::size_t size)`]
 [variablelist
+[[Preconditions:] [`sp` is valid, `minimum_stacksize() > size` and
+`! is_stack_unbound() && ( maximum_stacksize() < size)`.]]
+[[Effects:] [Deallocates the stack space.]]
+]
+
+[endsect]
+
+
+[section:simple_stack_allocator Template `simple_stack_allocator< size_t, size_t, size_t >`]
+
+__boost_context__ provides the class `simple_stack_allocator` which models
+the __stack_allocator_concept__ concept. The template arguments define the
+limits for the stack size.
+The class simply allocates memory on the heap via `calloc()` - in contrast to
+`guarde_stack_allocator` no guard page is appended.
+
+[important The user is responsible for valid stack limits (e.g. maximum, minimum
+and default stacksize.]
+
+        template< size_t Max, size_t Default, size_t Min >
+        class simple_stack_allocator
+        {
+            static std::size_t maximum_stacksize();
+
+            static std::size_t default_stacksize();
+
+            static std::size_t minimum_stacksize();
+
+            void * allocate( std::size_t size);
+
+            void deallocate( void * sp, std::size_t size);
+        }
+
+[heading `static std::size_t maximum_stacksize()`]
+[variablelist
+[[Returns:] [Returns the maximum size in bytes of stack defined by the first
+tempalte argument.]]
+]
+
+[heading `static std::size_t default_stacksize()`]
+[variablelist
+[[Returns:] [Returns a default stack size in bytes defined by the second
+template argument.]]
+]
+
+[heading `static std::size_t minimum_stacksize()`]
+[variablelist
+[[Returns:] [Returns the minimum size in bytes of stack defined by the
+third template argument.]]
+]
+
+[heading `void * allocate( std::size_t size)`]
+[variablelist
+[[Preconditions:] [`minimum_stacksize() > size` and
+`maximum_stacksize() < size`.]]
+[[Effects:] [Allocates memory of `size` bytes (memory is set to NULL).]]
+[[Returns:] [Returns pointer to the start address of the new stack. Depending
+on the architecture the stack grows downwards/upwards the returned address is
+the highest/lowest address of the stack.]]
+]
+
+[heading `void deallocate( void * sp, std::size_t size)`]
+[variablelist
+[[Preconditions:] [`sp` is valid, `minimum_stacksize() > size` and
+`maximum_stacksize() < size`.]]
 [[Effects:] [Deallocates the stack space.]]
-[[Throws:] [Nothing.]]
 ]
 
 [endsect]
Modified: trunk/libs/context/doc/todo.qbk
==============================================================================
--- trunk/libs/context/doc/todo.qbk	(original)
+++ trunk/libs/context/doc/todo.qbk	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -7,7 +7,7 @@
 
 [section:todo Todo]
 
-* provide support for SPARC, SuperH( SH4), S/390
+* provide support for SPARC, SuperH (SH4), S/390
 * support split-stack feature from gcc/gold linker
 
 [endsect]
Modified: trunk/libs/context/example/exit.cpp
==============================================================================
--- trunk/libs/context/example/exit.cpp	(original)
+++ trunk/libs/context/example/exit.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -14,39 +14,38 @@
 
 namespace ctx = boost::ctx;
 
-ctx::fcontext_t fc1, fc2;
+ctx::fcontext_t * fc1;
+ctx::fcontext_t * fc2;
 
 void f1( intptr_t)
 {
         std::cout << "f1: entered" << std::endl;
-        std::cout << "f1: call jump_fcontext( & fc1, & fc2, 0)" << std::endl;
-        ctx::jump_fcontext( & fc1, & fc2, 0);
+        std::cout << "f1: call jump_fcontext( fc1, fc2, 0)" << std::endl;
+        ctx::jump_fcontext( fc1, fc2, 0);
         std::cout << "f1: return" << std::endl;
 }
 
 void f2( intptr_t)
 {
         std::cout << "f2: entered" << std::endl;
-        std::cout << "f2: call jump_fcontext( & fc2, & fc1, 0)" << std::endl;
-        ctx::jump_fcontext( & fc2, & fc1, 0);
+        std::cout << "f2: call jump_fcontext( fc2, fc1, 0)" << std::endl;
+        ctx::jump_fcontext( fc2, fc1, 0);
         BOOST_ASSERT( false && ! "f2: never returns");
 }
 
 int main( int argc, char * argv[])
 {
         ctx::fcontext_t fcm;
-        ctx::stack_allocator alloc;
+        ctx::guarded_stack_allocator alloc;
 
-        fc1.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
-        fc1.fc_stack.size = ctx::minimum_stacksize();
-        ctx::make_fcontext( & fc1, f1);
-
-        fc2.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
-        fc2.fc_stack.size = ctx::minimum_stacksize();
-        ctx::make_fcontext( & fc2, f2);
+        void * sp1 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize());
+        fc1 = ctx::make_fcontext( sp1, ctx::guarded_stack_allocator::default_stacksize(), f1);
 
-        std::cout << "main: call start_fcontext( & fcm, & fc1, 0)" << std::endl;
-        ctx::jump_fcontext( & fcm, & fc1, 0);
+        void * sp2 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize());
+        fc2 = ctx::make_fcontext( sp2, ctx::guarded_stack_allocator::default_stacksize(), f2);
+
+        std::cout << "main: call start_fcontext( & fcm, fc1, 0)" << std::endl;
+        ctx::jump_fcontext( & fcm, fc1, 0);
 
         std::cout << "main: done" << std::endl;
         BOOST_ASSERT( false && ! "main: never returns");
Modified: trunk/libs/context/example/jump.cpp
==============================================================================
--- trunk/libs/context/example/jump.cpp	(original)
+++ trunk/libs/context/example/jump.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -14,39 +14,47 @@
 
 namespace ctx = boost::ctx;
 
-ctx::fcontext_t fcm, fc1, fc2;
+ctx::fcontext_t fcm;
+ctx::fcontext_t * fc1 = 0;
+ctx::fcontext_t * fc2 = 0;
 
 void f1( intptr_t)
 {
         std::cout << "f1: entered" << std::endl;
-        std::cout << "f1: call jump_fcontext( & fc1, & fc2, 0)" << std::endl;
-        ctx::jump_fcontext( & fc1, & fc2, 0);
+        std::cout << "f1: call jump_fcontext( fc1, fc2, 0)" << std::endl;
+        ctx::jump_fcontext( fc1, fc2, 0);
         std::cout << "f1: return" << std::endl;
-        ctx::jump_fcontext( & fc1, & fcm, 0);
+        ctx::jump_fcontext( fc1, & fcm, 0);
 }
 
 void f2( intptr_t)
 {
         std::cout << "f2: entered" << std::endl;
-        std::cout << "f2: call jump_fcontext( & fc2, & fc1, 0)" << std::endl;
-        ctx::jump_fcontext( & fc2, & fc1, 0);
+        std::cout << "f2: call jump_fcontext( fc2, fc1, 0)" << std::endl;
+        ctx::jump_fcontext( fc2, fc1, 0);
         BOOST_ASSERT( false && ! "f2: never returns");
 }
 
 int main( int argc, char * argv[])
 {
-        ctx::stack_allocator alloc1, alloc2;
+        ctx::guarded_stack_allocator alloc;
 
-        fc1.fc_stack.sp = alloc1.allocate(ctx::minimum_stacksize());
-        fc1.fc_stack.size = ctx::minimum_stacksize();
-        ctx::make_fcontext( & fc1, f1);
-
-        fc2.fc_stack.sp = alloc2.allocate(ctx::minimum_stacksize());
-        fc2.fc_stack.size = ctx::minimum_stacksize();
-        ctx::make_fcontext( & fc2, f2);
+        void * base1 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize());
+        BOOST_ASSERT( base1);
+        fc1 = ctx::make_fcontext( base1, ctx::guarded_stack_allocator::default_stacksize(), f1);
+        BOOST_ASSERT( fc1);
+        BOOST_ASSERT( base1 == fc1->fc_stack.sp);
+        BOOST_ASSERT( ctx::guarded_stack_allocator::default_stacksize() == fc1->fc_stack.size);
+
+        void * base2 = alloc.allocate(ctx::guarded_stack_allocator::default_stacksize());
+        BOOST_ASSERT( base2);
+        fc2 = ctx::make_fcontext( base2, ctx::guarded_stack_allocator::default_stacksize(), f2);
+        BOOST_ASSERT( fc2);
+        BOOST_ASSERT( base2 == fc2->fc_stack.sp);
+        BOOST_ASSERT( ctx::guarded_stack_allocator::default_stacksize() == fc2->fc_stack.size);
 
-        std::cout << "main: call start_fcontext( & fcm, & fc1, 0)" << std::endl;
-        ctx::jump_fcontext( & fcm, & fc1, 0);
+        std::cout << "main: call start_fcontext( & fcm, fc1, 0)" << std::endl;
+        ctx::jump_fcontext( & fcm, fc1, 0);
 
         std::cout << "main: done" << std::endl;
 
Modified: trunk/libs/context/example/transfer.cpp
==============================================================================
--- trunk/libs/context/example/transfer.cpp	(original)
+++ trunk/libs/context/example/transfer.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -15,7 +15,8 @@
 
 namespace ctx = boost::ctx;
 
-ctx::fcontext_t fc1, fcm;
+ctx::fcontext_t fcm;
+ctx::fcontext_t * fc1;
 
 typedef std::pair< int, int >   pair_t;
 
@@ -23,25 +24,25 @@
 {
     pair_t * p = ( pair_t *) param;
 
-    p = ( pair_t *) ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
+    p = ( pair_t *) ctx::jump_fcontext( fc1, & fcm, ( intptr_t) ( p->first + p->second) );
 
-    ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
+    ctx::jump_fcontext( fc1, & fcm, ( intptr_t) ( p->first + p->second) );
 }
 
 int main( int argc, char * argv[])
 {
-    ctx::stack_allocator alloc;
+    typedef ctx::simple_stack_allocator< 256 * 1024, 64 * 1024, 8 * 1024 > alloc_t;
+    alloc_t alloc;
 
-    fc1.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
-    fc1.fc_stack.size = ctx::minimum_stacksize();
-    ctx::make_fcontext( & fc1, f1);
+    void * sp = alloc.allocate(alloc_t::default_stacksize());
+    fc1 = ctx::make_fcontext( sp, alloc_t::default_stacksize(), f1);
 
     pair_t p( std::make_pair( 2, 7) );
-    int res = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & p);
+    int res = ( int) ctx::jump_fcontext( & fcm, fc1, ( intptr_t) & p);
     std::cout << p.first << " + " << p.second << " == " << res << std::endl;
 
     p = std::make_pair( 5, 6);
-    res = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & p);
+    res = ( int) ctx::jump_fcontext( & fcm, fc1, ( intptr_t) & p);
     std::cout << p.first << " + " << p.second << " == " << res << std::endl;
 
     std::cout << "main: done" << std::endl;
Modified: trunk/libs/context/performance/performance.cpp
==============================================================================
--- trunk/libs/context/performance/performance.cpp	(original)
+++ trunk/libs/context/performance/performance.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -34,7 +34,7 @@
 
 bool pres_fpu = false;
 
-#define CALL_FCONTEXT(z,n,unused) ctx::jump_fcontext( & fcm, & fc, 7, pres_fpu);
+#define CALL_FCONTEXT(z,n,unused) ctx::jump_fcontext( & fcm, fc, 7, pres_fpu);
 
 #ifdef BOOST_USE_UCONTEXT
 # define CALL_UCONTEXT(z,n,unused) ::swapcontext( & ucm, & uc);
@@ -43,7 +43,7 @@
 #define CALL_FUNCTION(z,n,unused) fn();
 
 
-ctx::fcontext_t fc, fcm;
+ctx::fcontext_t fcm, * fc;
 
 #ifdef BOOST_USE_UCONTEXT
 ucontext_t uc, ucm;
@@ -51,7 +51,7 @@
 
 
 static void f1( intptr_t)
-{ while ( true) ctx::jump_fcontext( & fc, & fcm, 7, pres_fpu); }
+{ while ( true) ctx::jump_fcontext( fc, & fcm, 7, pres_fpu); }
 
 #ifdef BOOST_USE_UCONTEXT
 static void f2()
@@ -65,12 +65,13 @@
 #ifdef BOOST_CONTEXT_CYCLE
 cycle_t test_fcontext_cycle( cycle_t ov)
 {
-    ctx::stack_allocator alloc;
-    fc.fc_stack.sp = alloc.allocate(ctx::default_stacksize());
-    fc.fc_stack.size = ctx::default_stacksize();
-    ctx::make_fcontext( & fc, f1);
+    ctx::guarded_stack_allocator alloc;
+    fc = ctx::make_fcontext(
+        alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()),
+        ctx::guarded_stack_allocator::default_stacksize(),
+        f1);
 
-    ctx::jump_fcontext( & fcm, & fc, 7, pres_fpu);
+    ctx::jump_fcontext( & fcm, fc, 7, pres_fpu);
 
     // cache warum-up
 BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
@@ -90,11 +91,11 @@
 # ifdef BOOST_USE_UCONTEXT
 cycle_t test_ucontext_cycle( cycle_t ov)
 {
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
     ::getcontext( & uc);
-    uc.uc_stack.ss_sp = alloc.allocate(ctx::default_stacksize());
-    uc.uc_stack.ss_size = ctx::default_stacksize();
+    uc.uc_stack.ss_sp = alloc.allocate(ctx::guarded_stack_allocator_stacksize());
+    uc.uc_stack.ss_size = ctx::guarded_stack_allocator_stacksize();
     ::makecontext( & uc, f2, 7);
 
     // cache warum-up
@@ -136,12 +137,13 @@
 #if _POSIX_C_SOURCE >= 199309L
 zeit_t test_fcontext_zeit( zeit_t ov)
 {
-    ctx::stack_allocator alloc;
-    fc.fc_stack.sp = alloc.allocate(ctx::default_stacksize());
-    fc.fc_stack.size = ctx::default_stacksize();
-    ctx::make_fcontext( & fc, f1);
+    ctx::guarded_stack_allocator alloc;
+    fc = ctx::make_fcontext(
+        alloc.allocate(ctx::guarded_stack_allocator::default_stacksize()),
+        ctx::guarded_stack_allocator::default_stacksize(),
+        f1);
 
-    ctx::jump_fcontext( & fcm, & fc, 7, pres_fpu);
+    ctx::jump_fcontext( & fcm, fc, 7, pres_fpu);
 
     // cache warum-up
 BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
@@ -161,11 +163,11 @@
 # ifdef BOOST_USE_UCONTEXT
 zeit_t test_ucontext_zeit( zeit_t ov)
 {
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
     ::getcontext( & uc);
-    uc.uc_stack.ss_sp = alloc.allocate(ctx::default_stacksize());
-    uc.uc_stack.ss_size = ctx::default_stacksize();
+    uc.uc_stack.ss_sp = alloc.allocate(ctx::guarded_stack_allocator_stacksize());
+    uc.uc_stack.ss_size = ctx::guarded_stack_allocator_stacksize();
     ::makecontext( & uc, f2, 7);
 
     // cache warum-up
Modified: trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -77,22 +77,22 @@
 .align 2
 .type make_fcontext,%function
 make_fcontext:
-    str     a2, [a1,#40]        @ save address of context function
-    ldr     a2, [a1,#44]        @ load address of context stack pointer (base)
+    stmfd   sp!, {a1-a3,lr}     @ save arguments of make_fcontext and return address on stack, SP % 8 == 0
+    sub     a1, #116            @ reserve space for fcontext_t at top of context stack
+    bl      align_stack_at_PLT     @ call align_stack, A1 contains address at 16 byte boundary after return
+                                @ == pointer to fcontext_t and address of context stack
 
-    push    {a1,lr}             @ save pointer to fcontext_t and return address, SP % 8 == 0
-    mov     a1, a2              @ context stack pointer as arg for align_stack
-    bl      align_stack_at_PLT     @ call align_stack
-    mov     a2, a1              @ begin of aligned context stack
-    pop     {a1,lr}             @ restore pointer to fcontext_t and return address
+    ldmfd   sp!, {a2-a4,lr}     @ restore arguments of make_fcontext and return address from stack
+    str     a2, [a1,#44]        @ save address of context stack (base) in fcontext_t
+    str     a3, [a1,#48]        @ save context stack size in fcontext_t
+    str     a4, [a1,#40]        @ save address of context function in fcontext_t
 
-    str     a2, [a1,#32]        @ save address in A2 as stack pointer for context function
+    str     a1, [a1,#32]        @ save address in A1 as stack pointer for context function
 
     adr     a2, finish          @ compute abs address of label finish
     str     a2, [a1,#36]        @ save address of finish as return address for context function
                                 @ entered after context function returns
 
-    mov     a1, #0
     bx      lr
 
 finish:
Modified: trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm
==============================================================================
--- trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm	(original)
+++ trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -114,27 +114,27 @@
     mov  ebp,         esp           ; set EBP to ESP 
     sub  esp,         010h          ; allocate stack space
 
-    mov  eax,         [ebp+08h]     ; load address of fcontext_t
-    mov  ecx,         [ebp+0ch]     ; load address of context function
-    mov  [eax+014h],  ecx           ; save address of context function
-    mov  edx,         [eax+018h]    ; load address of context stack (base)
-    mov  ecx,         [eax+01ch]    ; load context stack size
-    neg  ecx                        ; negate stack size for LEA instruction (== substraction)
-    lea  edx,         [edx+ecx]     ; compute top address of context stack
-    mov  [eax+020h],  edx           ; save bottom address of context stack (limit)
-    mov  edx,         [eax+018h]    ; load address of context stack (base)
-
-    mov   [esp+04h],  eax           ; save pointer to fcontext_t
-    mov   [esp],      edx           ; context stack as arg for align_stack
-    call  align_stack               ; call align_stack
-    mov   edx,        eax           ; begin of aligned context stack
-    mov   eax,        [esp+04h]     ; restore pointer to fcontext_t
-    
+    mov  eax,         [ebp+08h]     ; load 1. arg of make_fcontext, pointer to context stack (base)
+    lea  eax,         [eax-034h]    ; reserve space for fcontext_t at top of context stack
+    mov  [esp],       eax           ; address in EAX becomes 1.arg of align_stack
+    call  align_stack               ; call align_stack, EAX contains address at 16 byte boundary after return
+                                    ; == pointer to fcontext_t and address of context stack
+
+    mov  ecx,         [ebp+08h]     ; load 1. arg of make_fcontext, pointer to context stack (base)
+    mov  [eax+018h],  ecx           ; save address of context stack (base) in fcontext_t
+    mov  edx,         [ebp+0ch]     ; load 2. arg of make_fcontext, context stack size
+    mov  [eax+01ch],  edx           ; save context stack size in fcontext_t
+    neg  edx                        ; negate stack size for LEA instruction (== substraction)
+    lea  ecx,         [ecx+edx]     ; compute bottom address of context stack (limit)
+    mov  [eax+020h],  ecx           ; save address of context stack (limit) in fcontext_t
+    mov  ecx,         [ebp+010h]    ; load 3. arg of make_fcontext, pointer to context function
+    mov  [eax+014h],  ecx           ; save address of context function in fcontext_t
+
     stmxcsr [eax+02ch]              ; save MMX control word
     fnstcw  [eax+030h]              ; save x87 control word
 
-    lea  edx,         [edx-01ch]    ; reserve space for last frame and seh on context stack, (ESP - 0x4) % 16 == 0
-    mov  [eax+010h],  edx           ; save address in EDX as stack pointer for context stack
+    lea  edx,         [eax-01ch]    ; reserve space for last frame and seh on context stack, (ESP - 0x4) % 16 == 0
+    mov  [eax+010h],  edx           ; save address in EDX as stack pointer for context function
 
     mov  ecx,         seh_fcontext  ; set ECX to exception-handler
     mov  [edx+018h],  ecx           ; save ECX as SEH handler
@@ -150,7 +150,6 @@
     add  esp,         010h          ; deallocate stack space
     pop  ebp
 
-    xor  eax,         eax
     ret
 
 finish:
Modified: trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -80,26 +80,29 @@
     movl   %esp,           %ebp         /* set EBP to ESP */
     subl   $0x10,          %esp         /* allocate stack space */
 
-    movl   0x8(%ebp),      %eax         /* load address of fcontext_t */
-    movl   0xc(%ebp),      %ecx         /* load address of context function */
-    movl   %ecx,           0x14(%eax)   /* save address of context function */
-    movl   0x18(%eax),     %edx         /* load address of context stack base */
-
-    movl  %ebx,            0x8(%esp)    /* save EBX */
-    movl  %eax,            0x4(%esp)    /* save pointer to fcontext_t */
-    movl  %edx,            (%esp)       /* context stack pointer as arg for align_stack */
+    movl   %ebx,           0x4(%esp)    /* save EBX */
+    movl   0x8(%ebp),      %eax         /* load 1. arg of make_fcontext, pointer to context stack (base) */
+    leal   -0x28(%eax),    %eax         /* reserve space for fcontext_t at top of context stack */
+    movl   %eax,           (%esp)       /* address in EAX becomes 1. arg of align_stack */
+
     call   1f
 1:  popl   %ebx                                    /* address of label 1 */
     addl   $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx     /* compute address of GOT and store it in EBX */
-    call   align_stack_at_PLT                         /* call align_stack */
-    movl   %eax,           %edx                    /* begin of aligned context stack */
-    movl   0x4(%esp),      %eax                    /* restore pointer to fcontext_t */
-    movl   0x8(%esp),      %ebx                    /* restore EBX */
+    call   align_stack_at_PLT                         /* call align_stack, EAX contains address at 16 byte boundary after return */
+                                                   /* == pointer to fcontext_t and address of context stack */
+    movl   0x4(%esp),      %ebx                    /* restore EBX */
+
+    movl   0x8(%ebp),      %edx         /* load 1. arg of make_fcontext, pointer to context stack (base) */
+    movl   %edx,           0x18(%eax)   /* save address of context stack (base) in fcontext_t */
+    movl   0xc(%ebp),      %edx         /* load 2. arg of make_fcontext, context stack size */
+    movl   %edx,           0x1c(%eax)   /* save stack size in fcontext_t */
+    movl   0x10(%ebp),     %edx         /* load 3. arg of make_fcontext, pointer to context function */
+    movl   %edx,           0x14(%eax)   /* save address of context function in fcontext_t */
 
     stmxcsr  0x20(%eax)                 /* save MMX control and status word */
     fnstcw   0x24(%eax)                 /* save x87 control word */
 
-    leal   -0xc(%edx),     %edx         /* reserve space for the last frame on context stack; (ESP - 0x4) % 16 == 0 */
+    leal   -0xc(%eax),     %edx         /* reserve space for the last frame on context stack; (ESP - 0x4) % 16 == 0 */
     movl   %edx,           0x10(%eax)   /* save address in EDX as stack pointer for context function */
 
     call   2f
@@ -111,7 +114,6 @@
     addl   $0x10,          %esp        /* deallocate stack space */
     pop    %ebp
 
-    xorl    %eax,          %eax
     ret
 
 finish:
Modified: trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -77,21 +77,23 @@
     movl   %esp,           %ebp         /* set EBP to ESP */
     subl   $0x10,          %esp         /* allocate stack space */
 
-    movl   0x8(%ebp),      %eax         /* load address of fcontext_t */
-    movl   0xc(%ebp),      %ecx         /* load address of context function */
-    movl   %ecx,           0x14(%eax)   /* save address of context function */
-    movl   0x18(%eax),     %edx         /* load address of context stack base */
-
-    movl   %eax,           0x4(%esp)    /* save pointer to fcontext_t */
-    movl   %edx,           (%esp)       /* context stack pointer as arg for align_stack */
-    call   _align_stack                 /* call align_stack */
-    movl   %eax,           %edx         /* begin of aligned context stack */
-    movl   0x4(%esp),      %eax         /* restore pointer to fcontext_t */
+    movl   0x8(%ebp),      %eax         /* load 1. arg of make_fcontext, pointer to context stack (base) */
+    leal   -0x28(%eax),    %eax         /* reserve space for fcontext_t at top of context stack */
+    movl   %eax,           (%esp)       /* address in EAX becomes 1. arg of align_stack */
+    call   _align_stack                 /* call align_stack, EAX contains address at 16 byte boundary after return */
+                                        /* ==pointer to fcontext_t and address of context stack */
+
+    movl   0x8(%ebp),      %edx         /* load 1. arg of make_fcontext, pointer to context stack (base) */
+    movl   %edx,           0x18(%eax)   /* save address of stack pointer (base) in fcontext_t */
+    movl   0xc(%ebp),      %edx         /* load 2. arg of make_fcontext, context stack size */
+    movl   %edx,           0x1c(%eax)   /* save stack size in fcontext_t */
+    movl   0x10(%ebp),     %edx         /* load 3. arg of make_fcontext, pointer to context function */
+    movl   %edx,           0x14(%eax)   /* save address of context fcuntion in fcontext_t */
 
     stmxcsr  0x20(%eax)                 /* save MMX control and status word */
     fnstcw   0x24(%eax)                 /* save x87 control word */
 
-    leal   -0xc(%edx),     %edx         /* reserve space for the last frame on context stack, (ESP - 0x4) % 16 == 0 */
+    leal   -0xc(%eax),     %edx         /* reserve space for the last frame on context stack, (ESP - 0x4) % 16 == 0 */
     movl   %edx,           0x10(%eax)   /* save address in EDX as stack pointer for context function */
 
     call   1f
@@ -103,7 +105,6 @@
     addl   $0x10,          %esp         /* deallocate stack space */
     pop    %ebp
 
-    xorl   %eax,           %eax
     ret
 
 finish:
Modified: trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -10,28 +10,28 @@
  *  -------------------------------------------------------------  *
  *  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  *
  *  -------------------------------------------------------------  *
- *  |  0  |  8  |  16 |  24 |  32 |  40 |  48 |  56 |  64 |  72 |  *
+ *  |  0  |  4  |  8  |  12 |  16 |  20 |  24 |  28 |  32 |  36 |  *
  *  -------------------------------------------------------------  *
- *  |  S0 |  S1 |  S2 |  S3 |  S4 |  S5 |  S6 |  S7 |  GP |  SP |  *
+ *  |  S0 |  S1 |  S2 |  S3 |  S4 |  S5 |  S6 |  S7 |  FP |  SP |  *
  *  -------------------------------------------------------------  *
  *  -------------------------------------------------------------  *
- *  |  10 |  11 |  12 |                                         |  *
+ *  |  10 |  11 |                                               |  *
  *  -------------------------------------------------------------  *
- *  |  80 |  88 |  96 |                                         |  *
+ *  |  40 |  44 |                                               |  *
  *  -------------------------------------------------------------  *
- *  |  S8 |  RA |  PC |                                         |  *
+ *  |  RA |  PC |                                               |  *
  *  -------------------------------------------------------------  *
  *  -------------------------------------------------------------  *
- *  |  13 |  14 |                                               |  *
+ *  |  12 |  13 |                                               |  *
  *  -------------------------------------------------------------  *
- *  | 104 | 112 |                                               |  *
+ *  |  48 |  52 |                                               |  *
  *  -------------------------------------------------------------  *
  *  |  sp | size|                                               |  *
  *  -------------------------------------------------------------  *
  *  -------------------------------------------------------------  *
- *  |  15 |  16 |  17 |  18 |  19 |  20 |                       |  *
+ *  |  14 |  15 |  16 |  17 |  18 |  19 |                       |  *
  *  -------------------------------------------------------------  *
- *  | 120 | 128 | 136 | 144 | 152 | 160 |                       |  *
+ *  |  56 |  64 |  72 |  80 |  88 |  96 |                       |  *
  *  -------------------------------------------------------------  *
  *  | F20 | F22 | F24 | F26 | F28 | F30 |                       |  *
  *  -------------------------------------------------------------  *
@@ -45,57 +45,53 @@
 .ent jump_fcontext
 jump_fcontext:
     sw      $s0, ($a0)      # save S0
-    sw      $s1, 8($a0)     # save S1
-    sw      $s2, 16($a0)    # save S2
-    sw      $s3, 24($a0)    # save S3
-    sw      $s4, 32($a0)    # save S4
-    sw      $s5, 40($a0)    # save S5
-    sw      $s6, 48($a0)    # save S6
-    sw      $s7, 56($a0)    # save S7
-    sw      $gp, 64($a0)    # save GP
-    sw      $sp, 72($a0)    # save SP
-    sw      $s8, 80($a0)    # save S8
-    sw      $ra, 88($a0)    # save RA
-    sw      $ra, 96($a0)    # save RA as PC
+    sw      $s1, 4($a0)     # save S1
+    sw      $s2, 8($a0)     # save S2
+    sw      $s3, 12($a0)    # save S3
+    sw      $s4, 16($a0)    # save S4
+    sw      $s5, 20($a0)    # save S5
+    sw      $s6, 24($a0)    # save S6
+    sw      $s7, 28($a0)    # save S7
+    sw      $fp, 32($a0)    # save FP
+    sw      $sp, 36($a0)    # save SP
+    sw      $ra, 40($a0)    # save RA
+    sw      $ra, 44($a0)    # save RA as PC
 
 #if defined(__mips_hard_float)
     beqz    $a3,  1f        # test if fpu env should be preserved 
-    s.d     $f20, 120($a0)  # save F20
-    s.d     $f22, 128($a0)  # save F22
-    s.d     $f24, 136($a0)  # save F24
-    s.d     $f26, 144($a0)  # save F26
-    s.d     $f28, 152($a0)  # save F28
-    s.d     $f30, 160($a0)  # save F30
-
-    l.d     $f20, 120($a1)  # restore F20
-    l.d     $f22, 128($a1)  # restore F22
-    l.d     $f24, 136($a1)  # restore F24
-    l.d     $f26, 144($a1)  # restore F26
-    l.d     $f28, 152($a1)  # restore F28
-    l.d     $f30, 160($a1)  # restore F30
+    s.d     $f20, 56($a0)   # save F20
+    s.d     $f22, 64($a0)   # save F22
+    s.d     $f24, 72($a0)   # save F24
+    s.d     $f26, 80($a0)   # save F26
+    s.d     $f28, 88($a0)   # save F28
+    s.d     $f30, 96($a0)   # save F30
+
+    l.d     $f20, 56($a1)   # restore F20
+    l.d     $f22, 64($a1)   # restore F22
+    l.d     $f24, 72($a1)   # restore F24
+    l.d     $f26, 80($a1)   # restore F26
+    l.d     $f28, 88($a1)   # restore F28
+    l.d     $f30, 96($a1)   # restore F30
 1:
 #endif
 
     lw      $s0, ($a1)      # restore S0
-    lw      $s1, 8($a1)     # restore S1
-    lw      $s2, 16($a1)    # restore S2
-    lw      $s3, 24($a1)    # restore S3
-    lw      $s4, 32($a1)    # restore S4
-    lw      $s5, 40($a1)    # restore S5
-    lw      $s6, 48($a1)    # restore S6
-    lw      $s7, 56($a1)    # restore S7
-    lw      $gp, 64($a1)    # restore GP
-    lw      $sp, 72($a1)    # restore SP
-    lw      $s8, 80($a1)    # restore S8
-    lw      $ra, 88($a1)    # restore RA
-    move    $a0, $s2        # restore void pointer as argument
+    lw      $s1, 4($a1)     # restore S1
+    lw      $s2, 8($a1)     # restore S2
+    lw      $s3, 12($a1)    # restore S3
+    lw      $s4, 16($a1)    # restore S4
+    lw      $s5, 20($a1)    # restore S5
+    lw      $s6, 24($a1)    # restore S6
+    lw      $s7, 28($a1)    # restore S7
+    lw      $fp, 32($a1)    # restore FP
+    lw      $sp, 36($a1)    # restore SP
+    lw      $ra, 40($a1)    # restore RA
 
     move    $v0, $a2        # use third arg as return value after jump
     move    $a0, $a2        # use third arg as first arg in context function
 
-    lw      $t9, 96($a1)    # load PC
+    lw      $t9, 44($a1)    # load PC
     jr      $t9             # jump to context
-    nop
 .end jump_fcontext
 .size jump_fcontext, .-jump_fcontext
 
@@ -110,31 +106,37 @@
 .cpload $t9
 .set    reorder
 #endif
-    addiu   $sp, $sp, -40       # allocate stack space (contains shadow space for subroutines)
-    sw      $ra, 36($sp)        # save return address
+    addiu   $sp, $sp, -48       # allocate stack space (contains shadow space for subroutines)
+    sw      $ra, 44($sp)        # save return address
+    sw      $fp, 40($sp)        # save frame pointer
+
+    sw      $a2, 48($sp)        # save 3. arg of make_fcontnext, pointer to context function
+    sw      $a1, 52($sp)        # save 2. arg of make_fcontext, context stack size
+    sw      $a0, 56($sp)        # save 1. arg of make_fcontext, pointer to context stack (base)
+    addiu   $a0, $a0, -104      # reserve space for fcontext_t at top of context stack
+    lw      $t9, %call16(align_stack)($gp) # compute adddress of align_stack via global pointer
+    jalr    $t9                 # call align_stack, V0 contains address at 16 byte boundary after return
+                                # == pointer to fcontext_t and address of context stack
+    lw      $a0, 56($sp)        # restore pointer to context stack (base)
+    lw      $a1, 52($sp)        # restore context stack size
+    lw      $a2, 48($sp)        # restore pointer to context function
+
+    sw      $a0, 48($v0)        # save address of context stack (base) in fcontext_t 
+    sw      $a1, 52($v0)        # save context stack size in fcontext_t 
+    sw      $a2, 44($v0)        # save address of context function in fcontext_t 
+    sw      $gp, ($v0)          # save global pointer in fcontext_t, S0 will contain address of global pointer
 
-    sw      $gp, 24($a0)        # save global pointer
-    sw      $a1, 96($a0)        # save address of context function
-    lw      $t0, 104($a0)       # load address of context stack pointer (base)
-
-    sw      $a0, 28($sp)        # save pointer to fcontext_t
-    move    $a0, $t0                       # context stack pointer as arg for align_stack
-    lw      $t9, %call16(align_stack)($gp) # address of align_stack
-    jalr    $t9                            # call align_stack
-    move    $t0, $v0            # begin of aligned context stack
-    lw      $a0, 28($sp)        # restore pointer to fcontext_t
-
-    addiu   $t0, $t0, -40       # reserve 16 byte (includes 4 byte shadow space), T0 % 16 == 0
-    sw      $t0, 72($a0)        # save address in T0 as stack pointer for context function, SP % 16 == 0
+    addiu   $t0, $v0, -48       # reserve 48 bytes (includes 4 byte shadow space), T0 % 16 == 0
+    sw      $t0, 36($v0)        # save address in T0 as stack pointer for context function, SP % 16 == 0
 
     la      $t9, finish         # compute abs address of label finish
-    sw      $t9, 88($a0)        # save address of finish as return address for context function
+    sw      $t9, 40($v0)        # save address of finish as return address for context function
                                 # entered after context function returns
 
-    lw      $ra, 36($sp)        # restore return address
-    addiu   $sp, $sp, 40        # deallocate stack space
+    lw      $fp, 40($sp)        # restore frame pointer
+    lw      $ra, 44($sp)        # restore return address
+    addiu   $sp, $sp, 48        # deallocate stack space
 
-    move    $v0, $zero
     jr      $ra
 
 finish:
@@ -142,7 +144,7 @@
     addiu   $sp, $sp, -32       # allocate stack space (contains shadow space for subroutines)
     sw      $ra, 28($sp)        # save return address
 
-    move    $gp, $s3                  # restore GP (global pointer)
+    move    $gp, $s0                  # restore GP (global pointer)
     move    $a0, $zero                # exit code is zero
     lw      $t9, %call16(_exit)($gp)  # address of exit
     jalr    $t9                       # exit application
Modified: trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -186,20 +186,25 @@
 make_fcontext:
     mflr    %r0                 # save return address into R0
     stw     %r0, 4(%r1)         # save return address on stack, set up stack frame
-    stwu    %r1, -32(%r1)       # allocate stack space, SP % 16 == 0
+    stwu    %r1, -48(%r1)       # allocate stack space, SP % 16 == 0
 
-    stw     %r4, 88(%r3)        # save address of context function
-    lwz     %r0, 92(%r3)        # load address of context stack pointer (base)
+    stw     %r5, 32(%r1)        # save 3. arg of make_fcontext, pointer to context function 
+    stw     %r4, 28(%r1)        # save 2. arg of make_fcontext, context stack size 
+    stw     %r3, 24(%r1)        # save 1. arg of make_fcontext, pointer to context stack (base) 
+
+    subi    %r3, %r3, 252       # reserve space for fcontext_t at top of context stack
+    bl      align_stack_at_plt     # call align_stack, R3 contains address at 16 byte boundary after return
+                                # == pointer to fcontext_t and address of context stack
+    lwz     %r4, 24(%r1)        # restore pointer to context stack (base)
+    lwz     %r5, 28(%r1)        # restore context stack size
+    lwz     %r6, 32(%r1)        # restore pointer to context function
+
+    stw     %r4, 92(%r3)        # save address of context stack (base) in fcontext_t
+    stw     %r5, 96(%r3)        # save context stack size in fcontext_t
+    stw     %r6, 88(%r3)        # save address of context function in fcontext_t
 
-    stw     %r3, 8(%r1)         # store pointer to fcontext_t on stack
-    mr.     %r3, %r0            # context stack as arg to align_stack
-    bl      align_stack_at_plt     # call align_stack
-    mr.     %r0, %r3            # load result into R0
-    lwz     %r3, 8(%r1)         # pop pointer to fcontext_t from stack
-
-    li      %r4, 56
-    subf    %r0, %r4, %r0       # reserve 24 bytes lingage + 32 bytes parameter area on context stack
-    stw     %r0, 76(%r3)        # save the aligned stack base
+    subi    %r0, %r3, 64        # reserve 64 bytes (linkage + parameter area), R0 % 16 == 0
+    stw     %r0, 76(%r3)        # save address in R0 as stack pointer for context function
 
     mflr    %r0                 # load LR
     bl      1f                  # jump to label 1
@@ -210,11 +215,10 @@
     stw     %r4, 84(%r3)             # save address of finish as return address for context function
                                      # entered after context function returns
 
-    addi    %r1, %r1, 32        # deallocate stack space
+    addi    %r1, %r1, 48        # deallocate stack space
     lwz     %r0, 4(%r1)         # load return address from stack, destroy stack frame
     mtlr    %r0                 # restore return address
 
-    li      %r3,  0
     blr
 
 finish:
Modified: trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -213,20 +213,25 @@
 .globl .make_fcontext
 .make_fcontext:
     mflr    %r0                 # save return address into R0
-    stw     %r0, 8(%r1)         # save return address on stack, set up stack frame
-    stwu    %r1, -64(%r1)       # allocate stack space, SP % 16 == 0
-
-    std     %r4, 176(%r3)       # save address of context function
-    ld      %r0, 184(%r3)       # load address of context stack pointer (base)
+    std     %r0, 8(%r1)         # save return address on stack, set up stack frame
+    stdu    %r1, -96(%r1)       # allocate stack space, SP % 16 == 0
 
-    stw     %r3, 16(%r1)        # store pointer to fcontext_t on stack
-    mr.     %r3, %r0            # context stack as arg to align_stack
-    bl      align_stack_at_plt     # call align_stack
-    mr.     %r0, %r3            # load result into R0
-    lwz     %r3, 16(%r1)        # pop pointer to fcontext_t from stack
+    std     %r5, 64(%r1)        # save 3. arg of make_fcontext, pointer to context function 
+    std     %r4, 56(%r1)        # save 2. arg of make_fcontext, context stack size 
+    std     %r3, 48(%r1)        # save 1. arg of make_fcontext, pointer to context stack (base) 
+
+    subi    %r3, %r3, 352       # reserve space for fcontext_t at top of context stack
+    bl      align_stack_at_plt     # call align_stack, R3 contains address at 16 byte boundary after return
+                                # == pointer to fcontext_t and address of context stack
+    ld      %r4, 48(%r1)        # restore pointer to context stack (base)
+    ld      %r5, 56(%r1)        # restore context stack size
+    ld      %r6, 64(%r1)        # restore pointer to context function
+
+    std     %r4, 184(%r3)       # save address of context stack (base) in fcontext_t
+    std     %r5, 192(%r3)       # save context stack size in fcontext_t
+    std     %r6, 176(%r3)       # save address of context function in fcontext_t
 
-    li      %r4, 64
-    subf    %r0, %r4, %r0       # 64 bytes on stack for parameter area (== 8 registers)
+    subf    %r0, %r3, 64        # 64 bytes on stack for parameter area (== 8 registers)
     std     %r0, 152(%r3)       # save the stack base
 
     mflr    %r0                 # load LR
@@ -242,7 +247,6 @@
     lwz     %r0, 8(%r1)         # load return address from stack, destroy stack frame
     mtlr    %r0                 # restore return address
 
-    li      %r3,  0
     blr
 
 finish:
Modified: trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm
==============================================================================
--- trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm	(original)
+++ trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -44,7 +44,7 @@
 ;  ----------------------------------------------------------------------------------
 ;  |   0x70  |   0x74  |   0x78  |   0x7c  |                                        |
 ;  ----------------------------------------------------------------------------------
-;  | fc_mxcsr|fc_x87_cw|       fc_xmm      |                                        |
+;  | fc_mxcsr|fc_x87_cw|     <padding>     |                                        |
 ;  ----------------------------------------------------------------------------------
 ;  ----------------------------------------------------------------------------------
 ;  |    32    |   33   |   34    |   35    |   36     |   37    |    38   |    39   |
@@ -112,31 +112,31 @@
 
     stmxcsr [rcx+070h]              ; save MMX control and status word
     fnstcw  [rcx+074h]              ; save x87 control word
-    mov     r10,         [rcx+078h] ; address of aligned XMM storage
-    movaps  [r10],       xmm6
-    movaps  [r10+010h],  xmm7
-    movaps  [r10+020h],  xmm8
-    movaps  [r10+030h],  xmm9
-    movaps  [r10+040h],  xmm10
-    movaps  [r10+050h],  xmm11
-    movaps  [r10+060h],  xmm12
-    movaps  [r10+070h],  xmm13
-    movaps  [r10+080h],  xmm14
-    movaps  [r10+090h],  xmm15
+    ; save XMM storage
+    movaps  [rcx+080h],   xmm6
+    movaps  [rcx+090h],   xmm7
+    movaps  [rcx+0100h],  xmm8
+    movaps  [rcx+0110h],  xmm9
+    movaps  [rcx+0120h],  xmm10
+    movaps  [rcx+0130h],  xmm11
+    movaps  [rcx+0140h],  xmm12
+    movaps  [rcx+0150h],  xmm13
+    movaps  [rcx+0160h],  xmm14
+    movaps  [rcx+0170h],  xmm15
 
     ldmxcsr [rdx+070h]              ; restore MMX control and status word
     fldcw   [rdx+074h]              ; restore x87 control word
-    mov     r10,         [rdx+078h] ; address of aligned XMM storage
-    movaps  xmm6,        [r10]
-    movaps  xmm7,        [r10+010h]
-    movaps  xmm8,        [r10+020h]
-    movaps  xmm9,        [r10+030h]
-    movaps  xmm10,       [r10+040h]
-    movaps  xmm11,       [r10+050h]
-    movaps  xmm12,       [r10+060h]
-    movaps  xmm13,       [r10+070h]
-    movaps  xmm14,       [r10+080h]
-    movaps  xmm15,       [r10+090h]
+    ; restore XMM storage
+    movaps  xmm6,        [rdx+080h]
+    movaps  xmm7,        [rdx+090h]
+    movaps  xmm8,        [rdx+0100h]
+    movaps  xmm9,        [rdx+0110h]
+    movaps  xmm10,       [rdx+0120h]
+    movaps  xmm11,       [rdx+0130h]
+    movaps  xmm12,       [rdx+0140h]
+    movaps  xmm13,       [rdx+0150h]
+    movaps  xmm14,       [rdx+0160h]
+    movaps  xmm15,       [rdx+0170h]
 nxt:
 
     lea     rax,         [rsp+08h]  ; exclude the return address
@@ -177,34 +177,38 @@
     mov  rbp,        rsp         ; set RBP to RSP
     sub  rsp,        040h        ; allocate stack space (contains shadow space for subroutines)
 
-    mov  [rcx+048h], rdx         ; save address of context function
-    mov  rdx,        [rcx+050h]  ; load address of context stack pointer (base)
-    mov  r8,         [rcx+058h]  ; load context stack size
-    neg  r8                      ; negate stack size for LEA instruction (== substraction)
-    lea  rdx,        [rdx+r8]    ; compute bottom address of context stack
-    mov  [rcx+060h], rdx         ; save bottom address of context stack (limit)
-    mov  rdx,        [rcx+050h]  ; load address of context stack pointer (base)
-
-    mov   [rbp-08h], rcx         ; save pointer to fcontext_t
-    mov   rcx,       rdx         ; context stack pointer as arg for align_stack
-    call  align_stack            ; call align_stack
-    mov   rdx,       rax         ; begin of aligned context stack
-    mov   rcx,       [rbp-08h]   ; restore pointer to fcontext_t
+	mov  [rbp-08h],  r8          ; save 3. arg of make_fcontext, pointer to context function
+    mov  [rbp-010h], rdx         ; save 2. arg of make_fcontext, context stack size
+    mov  [rbp-018h], rcx         ; save 1. arg of make_fcontext, pointer to context stack (base)
+    lea  rcx,        [rcx-0180h] ; reserve space for fcontext_t at top of context stack
+    call align_stack             ; align context stack, RAX contains address at 16 byte boundary
+                                 ; == pointer to fcontext_t and address of context stack
+
+    mov  r8,         [rbp-08h]   ; restore pointer to context function
+    mov  rdx,        [rbp-010h]  ; restore context stack size
+    mov  rcx,        [rbp-018h]  ; restore pointer to context stack (base)
+
+    mov  [rax+048h], r8          ; save address of context function in fcontext_t
+    mov  [rax+058h], rdx         ; save context stack size in fcontext_t
+    mov  [rax+050h], rcx         ; save address of context stack pointer (base) in fcontext_t
+
+    neg  rdx                     ; negate stack size for LEA instruction (== substraction)
+    lea  rcx,        [rcx+rdx]   ; compute bottom address of context stack (limit)
+    mov  [rax+060h], rcx         ; save bottom address of context stack (limit) in fcontext_t
 
-    stmxcsr [rcx+070h]           ; save MMX control and status word
-    fnstcw  [rcx+074h]           ; save x87 control word
+    stmxcsr [rax+070h]           ; save MMX control and status word
+    fnstcw  [rax+074h]           ; save x87 control word
 
-    lea  rdx,        [rdx-028h]  ; reserve 32byte shadow space + return address on stack, (RSP - 0x8) % 16 == 0
-    mov  [rcx+040h], rdx         ; save address in RDX as stack pointer for context function
+    lea  rdx,        [rax-028h]  ; reserve 32byte shadow space + return address on stack, (RSP - 0x8) % 16 == 0
+    mov  [rax+040h], rdx         ; save address in RDX as stack pointer for context function
 
-    lea  rax,        finish      ; compute abs address of label finish
-    mov  [rdx],      rax         ; save address of finish as return address for context function
+    lea  rcx,        finish      ; compute abs address of label finish
+    mov  [rdx],      rcx         ; save address of finish as return address for context function
                                  ; entered after context function returns
 
     add  rsp,        040h        ; deallocate shadow space
     pop  rbp                     ; restore previous frame pointer
 
-    xor  rax,        rax
     ret
 
 finish:
Modified: trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -88,32 +88,36 @@
 make_fcontext:
     pushq   %rbp                       /* save previous frame pointer; get the stack 16 byte aligned */
     movq    %rsp,           %rbp       /* set RBP to RSP */
-    subq    $0x10,          %rsp       /* allocate stack space */ 
+    subq    $0x20,          %rsp       /* allocate stack space */
 
-    movq   %rsi,            0x38(%rdi) /* save address of context function */
-    movq   0x40(%rdi),      %rdx       /* load address of context stack base */
+    movq   %rdx,            0x10(%rsp) /* save 3. arg of make_fcontext, pointer to context function */
+    movq   %rsi,            0x8(%rsp)  /* save 2. arg of make_fcontext, context stack size */
+    movq   %rdi,            (%rsp)     /* save 1. arg of make_fcontext, pointer to context stack (base) */
+    leaq   -0x58(%rdi),     %rdi       /* reserve space for fcontext_t at top of context stack */
+    call   align_stack_at_PLT             /* align context stack, RAX contains address at 16 byte boundary afte return */
+                                       /* == pointer to fcontext_t and address of context stack */
+    movq   (%rsp),          %rdi       /* restore pointer to context stack (base) */
+    movq   0x8(%rsp),       %rsi       /* restore context stack size */
+    movq   0x10(%rsp),      %rdx       /* restore pointer to context function */
+
+    movq   %rdi,            0x40(%rax) /* save address of context stack pointer (base) in fcontext_t */
+    movq   %rsi,            0x48(%rax) /* save context stack size in fcontext_t */
+    movq   %rdx,            0x38(%rax) /* save address of context function in fcontext_t */
 
-    movq   %rdi,            (%rsp)     /* save pointer to fcontext_t */
-    movq   %rdx,            %rdi       /* context stack pointer as arg for align_stack */
-    call   align_stack_at_PLT             /* align context stack */
-    movq   %rax,            %rdx       /* begin of aligned context stack */
-    movq   (%rsp),          %rdi       /* restore pointer to fcontext_t */
+    stmxcsr  0x50(%rax)                /* save MMX control and status word */
+    fnstcw   0x54(%rax)                /* save x87 control word */
 
-    stmxcsr  0x50(%rdi)                /* save MMX control and status word */
-    fnstcw   0x54(%rdi)                /* save x87 control word */
-
-    leaq   -0x8(%rdx),      %rdx       /* reserve space for the last frame on context stack, (RSP - 0x8) % 16 == 0 */
-    movq   %rdx,            0x30(%rdi) /* save address in RDX as stack pointer for context function */
+    leaq   -0x8(%rax),      %rdx       /* reserve space for the return address on context stack, (RSP - 0x8) % 16 == 0 */
+    movq   %rdx,            0x30(%rax) /* save address in RDX as stack pointer for context function */
 
     leaq   finish(%rip),    %rcx       /* compute abs address of label finish */
     movq   %rcx,            (%rdx)     /* save address of finish as return address for context function */
                                        /* entered after context function returns */
 
-    addq   $0x10,           %rsp       /* deallocate shadow space */      
+    addq   $0x20,           %rsp       /* deallocate shadow space */      
     popq   %rbp                        /* restore previous frame pointer */
 
-    xorq   %rax,            %rax
-    ret
+    ret                                /* return pointer to fcontext_t placed on context stack */
 
 finish:
     /* RSP points to same address as RSP on entry of context function + 0x8 */
Modified: trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S	(original)
+++ trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -85,32 +85,36 @@
 _make_fcontext:
     pushq   %rbp                       /* save previous frame pointer; get the stack 16 byte aligned */
     movq    %rsp,           %rbp       /* set RBP to RSP */
-    subq    $0x10,          %rsp       /* allocate stack space */ 
+    subq    $0x20,          %rsp       /* allocate stack space */
 
-    movq   %rsi,            0x38(%rdi) /* save address of context function */
-    movq   0x40(%rdi),      %rdx       /* load address of context stack base */
+    movq   %rdx,            0x10(%rsp) /* save 3. arg of make_fcontext, pointer to context function */
+    movq   %rsi,            0x8(%rsp)  /* save 2. arg of make_fcontext, context stack size */
+    movq   %rdi,            (%rsp)     /* save 1. arg of make_fcontext, pointer to context stack (base) */
+    leaq   -0x58(%rdi),     %rdi       /* reserve space for fcontext_t at top of context stack */
+    call   _align_stack                /* align context stack, RAX contains address at 16 byte boundary */
+                                       /* == pointer to fcontext_t and address of context stack */
+    movq   (%rsp),          %rdi       /* restore pointer to context stack (base) */
+    movq   0x8(%rsp),       %rsi       /* restore context stack size */
+    movq   0x10(%rsp),      %rdx       /* restore pointer to context function */
+
+    movq   %rdi,            0x40(%rax) /* save address of stack pointer (base) in fcontext_t */
+    movq   %rsi,            0x48(%rax) /* save stack size in fcontext_t */
+    movq   %rdx,            0x38(%rax) /* save address of context function in fcontext_t */
 
-    movq   %rdi,            (%rsp)     /* save pointer to fcontext_t */
-    movq   %rdx,            %rdi       /* context stack pointer as arg for align_stack */
-    call   _align_stack                /* call align_stack */
-    movq   %rax,            %rdx       /* begin of aligned context stack */
-    movq   (%rsp),          %rdi       /* restore pointer to fcontext_t */
+    stmxcsr  0x50(%rax)                /* save MMX control and status word */
+    fnstcw   0x54(%rax)                /* save x87 control word */
 
-    stmxcsr  0x50(%rdi)                /* save MMX control and status word */
-    fnstcw   0x54(%rdi)                /* save x87 control word */
-
-    leaq   -0x8(%rdx),      %rdx       /* reserve space for the last frame on context stack, (RSP - 0x8) % 16 == 0 */
-    movq   %rdx,            0x30(%rdi) /* save address in RDX as stack pointer for context function */
+    leaq   -0x8(%rax),      %rdx       /* reserve space for the return address on context stack, (RSP - 0x8) % 16 == 0 */
+    movq   %rdx,            0x30(%rax) /* save address in RDX as stack pointer for context function */
 
     leaq   finish(%rip),    %rcx       /* compute abs address of label finish */
     movq   %rcx,            (%rdx)     /* save address of finish as return address for context function */
                                        /* entered after context function returns */
 
-    addq   $0x10,           %rsp       /* deallocate shadow space */      
+    addq   $0x20,           %rsp       /* deallocate shadow space */      
     popq   %rbp                        /* restore previous frame pointer */
 
-    xorq   %rax,            %rax
-    ret
+    ret                                /* return pointer to fcontext_t placed on context stack */
 
 finish:
     /* RSP points to same address as RSP on entry of context function + 0x8 */
Added: trunk/libs/context/src/guarded_stack_allocator_posix.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/context/src/guarded_stack_allocator_posix.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -0,0 +1,152 @@
+
+//          Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_CONTEXT_SOURCE
+
+#include <boost/context/guarded_stack_allocator.hpp>
+
+extern "C" {
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+}
+
+#if _POSIX_C_SOURCE >= 200112L
+
+#include <algorithm>
+#include <cmath>
+#include <cstring>
+#include <stdexcept>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/context/fcontext.hpp>
+#include <boost/context/utils.hpp>
+
+#if !defined (SIGSTKSZ)
+# define SIGSTKSZ (8 * 1024)
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_PREFIX
+#endif
+
+namespace {
+
+static rlimit stacksize_limit_()
+{
+    rlimit limit;
+    // conforming to POSIX.1-2001
+    const int result = ::getrlimit( RLIMIT_STACK, & limit);
+    BOOST_ASSERT( 0 == result);
+    return limit;
+}
+
+static rlimit stacksize_limit()
+{
+    static rlimit limit = stacksize_limit_();
+    return limit;
+}
+
+static std::size_t page_count( std::size_t stacksize)
+{
+    return static_cast< std::size_t >( 
+        std::ceil(
+            static_cast< float >( stacksize) / boost::ctx::pagesize() ) );
+}
+
+}
+
+namespace boost {
+namespace ctx {
+
+bool
+guarded_stack_allocator::is_stack_unbound()
+{ return RLIM_INFINITY == stacksize_limit().rlim_max; }
+
+std::size_t
+guarded_stack_allocator::maximum_stacksize()
+{
+    BOOST_ASSERT( ! is_stack_unbound() );
+    return static_cast< std::size_t >( stacksize_limit().rlim_max);
+}
+
+std::size_t
+guarded_stack_allocator::minimum_stacksize()
+{ return SIGSTKSZ + sizeof( fcontext_t) + 15; }
+
+std::size_t
+guarded_stack_allocator::default_stacksize()
+{
+    std::size_t size = 64 * 1024; // 64 kB
+    if ( is_stack_unbound() )
+        return std::max( size, minimum_stacksize() );
+    
+    BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
+    return maximum_stacksize() == minimum_stacksize()
+        ? minimum_stacksize()
+        : std::min( size, maximum_stacksize() );
+}
+
+void *
+guarded_stack_allocator::allocate( std::size_t size) const
+{
+    BOOST_ASSERT( minimum_stacksize() <= size);
+    BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
+
+    const std::size_t pages( page_count( size) + 1); // add one guard page
+    const std::size_t size_( pages * pagesize() );
+    BOOST_ASSERT( 0 < size && 0 < size_);
+
+    const int fd( ::open("/dev/zero", O_RDONLY) );
+    BOOST_ASSERT( -1 != fd);
+    // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+    void * limit =
+# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+        ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+# else
+        ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+# endif
+    ::close( fd);
+    if ( ! limit) throw std::bad_alloc();
+
+    std::memset( limit, size_, '\0');
+
+    // conforming to POSIX.1-2001
+    const int result( ::mprotect( limit, pagesize(), PROT_NONE) );
+    BOOST_ASSERT( 0 == result);
+
+    return static_cast< char * >( limit) + size_;
+}
+
+void
+guarded_stack_allocator::deallocate( void * vp, std::size_t size) const
+{
+    BOOST_ASSERT( vp);
+    BOOST_ASSERT( minimum_stacksize() <= size);
+    BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
+
+    const std::size_t pages = page_count( size) + 1;
+    const std::size_t size_ = pages * pagesize();
+    BOOST_ASSERT( 0 < size && 0 < size_);
+    void * limit = static_cast< char * >( vp) - size_;
+    // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+    ::munmap( limit, size_);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_SUFFIX
+#endif
+
+#endif
Added: trunk/libs/context/src/guarded_stack_allocator_windows.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/context/src/guarded_stack_allocator_windows.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -0,0 +1,155 @@
+
+//          Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_CONTEXT_SOURCE
+#define NOMINMAX
+
+#include <boost/context/guarded_stack_allocator.hpp>
+
+extern "C" {
+#include <windows.h>
+}
+
+#include <algorithm>
+#include <cmath>
+#include <csignal>
+#include <cstring>
+#include <stdexcept>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+
+#include <boost/context/utils.hpp>
+
+# if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4244 4267)
+# endif
+
+// x86_64
+// test x86_64 before i386 because icc might
+// define __i686__ for x86_64 too
+#if defined(__x86_64__) || defined(__x86_64) \
+    || defined(__amd64__) || defined(__amd64) \
+    || defined(_M_X64) || defined(_M_AMD64)
+
+// Windows seams not to provide a constant or function
+// telling the minimal stacksize
+# define MIN_STACKSIZE  8 * 1024
+#else
+# define MIN_STACKSIZE  4 * 1024
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_PREFIX
+#endif
+
+namespace {
+
+static SYSTEM_INFO system_info_()
+{
+    SYSTEM_INFO si;
+    ::GetSystemInfo( & si);
+    return si;
+}
+
+static SYSTEM_INFO system_info()
+{
+    static SYSTEM_INFO si = system_info_();
+    return si;
+}
+
+static std::size_t page_count( std::size_t stacksize)
+{
+    return static_cast< std::size_t >(
+        std::ceil(
+            static_cast< float >( stacksize) / boost::ctx::pagesize() ) );
+}
+
+}
+
+namespace boost {
+namespace ctx {
+
+// Windows seams not to provide a limit for the stacksize
+bool
+guarded_stack_allocator::is_stack_unbound()
+{ return true; }
+
+// because Windows seams not to provide a limit for maximum stacksize
+// maximum_stacksize() can never be called (pre-condition ! is_stack_unbound() )
+std::size_t
+guarded_stack_allocator::maximum_stacksize()
+{
+    BOOST_ASSERT( ! is_stack_unbound() );
+    return  1 * 1024 * 1024 * 1024; // 1GB
+}
+
+// because Windows seams not to provide a limit for minimum stacksize
+std::size_t
+guarded_stack_allocator::minimum_stacksize()
+{ return MIN_STACKSIZE; }
+
+std::size_t
+guarded_stack_allocator::default_stacksize()
+{
+    std::size_t size = 64 * 1024; // 64 kB
+    if ( is_stack_unbound() )
+        return std::max( size, minimum_stacksize() );
+    
+    BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
+    return maximum_stacksize() == minimum_stacksize()
+        ? minimum_stacksize()
+        : std::min( size, maximum_stacksize() );
+}
+
+void *
+guarded_stack_allocator::allocate( std::size_t size) const
+{
+    BOOST_ASSERT( minimum_stacksize() <= size);
+    BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
+
+    const std::size_t pages( page_count( size) + 1); // add one guard page
+    const std::size_t size_ = pages * pagesize();
+    BOOST_ASSERT( 0 < size && 0 < size_);
+
+    void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
+    if ( ! limit) throw std::bad_alloc();
+
+    std::memset( limit, size_, '\0');
+
+    DWORD old_options;
+    const BOOL result = ::VirtualProtect(
+        limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
+    BOOST_ASSERT( FALSE != result);
+
+    return static_cast< char * >( limit) + size_;
+}
+
+void
+guarded_stack_allocator::deallocate( void * vp, std::size_t size) const
+{
+    BOOST_ASSERT( vp);
+    BOOST_ASSERT( minimum_stacksize() <= size);
+    BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
+
+    const std::size_t pages = page_count( size) + 1;
+    const std::size_t size_ = pages * pagesize();
+    BOOST_ASSERT( 0 < size && 0 < size_);
+    void * limit = static_cast< char * >( vp) - size_;
+    ::VirtualFree( limit, 0, MEM_RELEASE);
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_SUFFIX
+#endif
+
+# if defined(BOOST_MSVC)
+# pragma warning(pop)
+# endif
Deleted: trunk/libs/context/src/stack_allocator_posix.cpp
==============================================================================
--- trunk/libs/context/src/stack_allocator_posix.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
+++ (empty file)
@@ -1,155 +0,0 @@
-
-//          Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-//    (See accompanying file LICENSE_1_0.txt or copy at
-//          http://www.boost.org/LICENSE_1_0.txt)
-
-#define BOOST_CONTEXT_SOURCE
-
-#include <boost/context/stack_allocator.hpp>
-
-extern "C" {
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <unistd.h>
-}
-
-#include <algorithm>
-#include <cmath>
-#include <cstring>
-#include <stdexcept>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/format.hpp>
-
-#if !defined (SIGSTKSZ)
-# define SIGSTKSZ (8 * 1024)
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-#  include BOOST_ABI_PREFIX
-#endif
-
-namespace {
-
-static rlimit stacksize_limit_()
-{
-    rlimit limit;
-    const int result = ::getrlimit( RLIMIT_STACK, & limit);
-    BOOST_ASSERT( 0 == result);
-    return limit;
-}
-
-static rlimit stacksize_limit()
-{
-    static rlimit limit = stacksize_limit_();
-    return limit;
-}
-
-static std::size_t pagesize()
-{
-    static std::size_t size = ::getpagesize();
-    return size;
-}
-
-static std::size_t page_count( std::size_t stacksize)
-{
-    return static_cast< std::size_t >( 
-        std::ceil(
-            static_cast< float >( stacksize) / pagesize() ) );
-}
-
-}
-
-namespace boost {
-namespace ctx {
-
-bool
-stack_allocator::is_stack_unbound()
-{ return RLIM_INFINITY == stacksize_limit().rlim_max; }
-
-std::size_t
-stack_allocator::maximum_stacksize()
-{
-    BOOST_ASSERT( ! is_stack_unbound() );
-    return static_cast< std::size_t >( stacksize_limit().rlim_max);
-}
-
-std::size_t
-stack_allocator::minimum_stacksize()
-{ return SIGSTKSZ; }
-
-std::size_t
-stack_allocator::default_stacksize()
-{
-    std::size_t size = 64 * 1024; // 64 kB
-    if ( is_stack_unbound() )
-        return std::max( size, minimum_stacksize() );
-    
-    BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
-    return maximum_stacksize() == minimum_stacksize()
-        ? minimum_stacksize()
-        : std::min( size, maximum_stacksize() );
-}
-
-void *
-stack_allocator::allocate( std::size_t size) const
-{
-    if ( minimum_stacksize() > size)
-        throw std::invalid_argument(
-            boost::str( boost::format("invalid stack size: must be at least %d bytes")
-                % minimum_stacksize() ) );
-
-    if ( ! is_stack_unbound() && ( maximum_stacksize() < size) )
-        throw std::invalid_argument(
-            boost::str( boost::format("invalid stack size: must not be larger than %d bytes")
-                % maximum_stacksize() ) );
-
-    const std::size_t pages( page_count( size) + 1); // add one guard page
-    const std::size_t size_( pages * pagesize() );
-    BOOST_ASSERT( 0 < size && 0 < size_);
-
-    const int fd( ::open("/dev/zero", O_RDONLY) );
-    BOOST_ASSERT( -1 != fd);
-    void * limit =
-# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
-        ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-# else
-        ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-# endif
-    ::close( fd);
-    if ( ! limit) throw std::bad_alloc();
-
-    std::memset( limit, size_, '\0');
-
-    const int result( ::mprotect( limit, pagesize(), PROT_NONE) );
-    BOOST_ASSERT( 0 == result);
-
-    return static_cast< char * >( limit) + size_;
-}
-
-void
-stack_allocator::deallocate( void * vp, std::size_t size) const
-{
-    if ( vp)
-    {
-        const std::size_t pages = page_count( size) + 1;
-        const std::size_t size_ = pages * pagesize();
-        BOOST_ASSERT( 0 < size && 0 < size_);
-        void * limit = static_cast< char * >( vp) - size_;
-        ::munmap( limit, size_);
-    }
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-#  include BOOST_ABI_SUFFIX
-#endif
Deleted: trunk/libs/context/src/stack_allocator_windows.cpp
==============================================================================
--- trunk/libs/context/src/stack_allocator_windows.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
+++ (empty file)
@@ -1,160 +0,0 @@
-
-//          Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-//    (See accompanying file LICENSE_1_0.txt or copy at
-//          http://www.boost.org/LICENSE_1_0.txt)
-
-#define BOOST_CONTEXT_SOURCE
-#define NOMINMAX
-
-#include <boost/context/stack_allocator.hpp>
-
-extern "C" {
-#include <windows.h>
-}
-
-#include <algorithm>
-#include <cmath>
-#include <csignal>
-#include <cstring>
-#include <stdexcept>
-
-#include <boost/config.hpp>
-#include <boost/assert.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/format.hpp>
-
-# if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable:4244 4267)
-# endif
-
-// x86_64
-// test x86_64 before i386 because icc might
-// define __i686__ for x86_64 too
-#if defined(__x86_64__) || defined(__x86_64) \
-    || defined(__amd64__) || defined(__amd64) \
-    || defined(_M_X64) || defined(_M_AMD64)
-# define MIN_STACKSIZE  9 * 1024 // 8kB will cause an excpetion on x64 Windows (exception handling)
-#else
-# define MIN_STACKSIZE  4 * 1024
-#endif
-
-#ifdef BOOST_HAS_ABI_HEADERS
-#  include BOOST_ABI_PREFIX
-#endif
-
-namespace {
-
-static SYSTEM_INFO system_info_()
-{
-    SYSTEM_INFO si;
-    ::GetSystemInfo( & si);
-    return si;
-}
-
-static SYSTEM_INFO system_info()
-{
-    static SYSTEM_INFO si = system_info_();
-    return si;
-}
-
-static std::size_t pagesize()
-{ return static_cast< std::size_t >( system_info().dwPageSize); }
-
-static std::size_t page_count( std::size_t stacksize)
-{
-    return static_cast< std::size_t >(
-        std::ceil(
-            static_cast< float >( stacksize) / pagesize() ) );
-}
-
-}
-
-namespace boost {
-namespace ctx {
-
-// Windows seams not to provide a limit for the stacksize
-bool
-stack_allocator::is_stack_unbound()
-{ return true; }
-
-// because Windows seams not to provide a limit for maximum stacksize
-// maximum_stacksize() can never be called (pre-condition ! is_stack_unbound() )
-std::size_t
-stack_allocator::maximum_stacksize()
-{
-    BOOST_ASSERT( ! is_stack_unbound() );
-    return  1 * 1024 * 1024 * 1024; // 1GB
-}
-
-// because Windows seams not to provide a limit for minimum stacksize
-std::size_t
-stack_allocator::minimum_stacksize()
-{ return MIN_STACKSIZE; }
-
-std::size_t
-stack_allocator::default_stacksize()
-{
-    std::size_t size = 64 * 1024; // 64 kB
-    if ( is_stack_unbound() )
-        return std::max( size, minimum_stacksize() );
-    
-    BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
-    return maximum_stacksize() == minimum_stacksize()
-        ? minimum_stacksize()
-        : std::min( size, maximum_stacksize() );
-}
-
-void *
-stack_allocator::allocate( std::size_t size) const
-{
-    if ( minimum_stacksize() > size)
-        throw std::invalid_argument(
-            boost::str( boost::format("invalid stack size: must be at least %d bytes")
-                % minimum_stacksize() ) );
-
-    if ( ! is_stack_unbound() && ( maximum_stacksize() < size) )
-        throw std::invalid_argument(
-            boost::str( boost::format("invalid stack size: must not be larger than %d bytes")
-                % maximum_stacksize() ) );
-
-    const std::size_t pages( page_count( size) + 1); // add one guard page
-    const std::size_t size_ = pages * pagesize();
-    BOOST_ASSERT( 0 < size && 0 < size_);
-
-    void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
-    if ( ! limit) throw std::bad_alloc();
-
-    std::memset( limit, size_, '\0');
-
-    DWORD old_options;
-    const BOOL result = ::VirtualProtect(
-        limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
-    BOOST_ASSERT( FALSE != result);
-
-    return static_cast< char * >( limit) + size_;
-}
-
-void
-stack_allocator::deallocate( void * vp, std::size_t size) const
-{
-    if ( vp)
-    {
-        const std::size_t pages = page_count( size) + 1;
-        const std::size_t size_ = pages * pagesize();
-        BOOST_ASSERT( 0 < size && 0 < size_);
-        void * limit = static_cast< char * >( vp) - size_;
-        ::VirtualFree( limit, 0, MEM_RELEASE);
-    }
-}
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-#  include BOOST_ABI_SUFFIX
-#endif
-
-# if defined(BOOST_MSVC)
-# pragma warning(pop)
-# endif
Added: trunk/libs/context/src/utils_posix.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/context/src/utils_posix.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -0,0 +1,39 @@
+
+//          Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_CONTEXT_SOURCE
+
+#include <boost/context/guarded_stack_allocator.hpp>
+
+extern "C" {
+#include <unistd.h>
+}
+
+#if _POSIX_C_SOURCE >= 200112L
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace ctx {
+
+std::size_t pagesize()
+{
+    // conform to POSIX.1-2001
+    static std::size_t size = ::sysconf( _SC_PAGESIZE);
+    return size;
+}
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_SUFFIX
+#endif
+
+#endif
Added: trunk/libs/context/src/utils_windows.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/context/src/utils_windows.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -0,0 +1,48 @@
+
+//          Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_CONTEXT_SOURCE
+
+#include <boost/context/guarded_stack_allocator.hpp>
+
+extern "C" {
+#include <windows.h>
+}
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_PREFIX
+#endif
+
+namespace {
+
+static SYSTEM_INFO system_info_()
+{
+    SYSTEM_INFO si;
+    ::GetSystemInfo( & si);
+    return si;
+}
+
+static SYSTEM_INFO system_info()
+{
+    static SYSTEM_INFO si = system_info_();
+    return si;
+}
+
+}
+
+namespace boost {
+namespace ctx {
+
+std::size_t pagesize()
+{ return static_cast< std::size_t >( system_info().dwPageSize); }
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+#  include BOOST_ABI_SUFFIX
+#endif
Modified: trunk/libs/context/test/test_context.cpp
==============================================================================
--- trunk/libs/context/test/test_context.cpp	(original)
+++ trunk/libs/context/test/test_context.cpp	2012-09-06 15:43:07 EDT (Thu, 06 Sep 2012)
@@ -10,6 +10,7 @@
 #include <string>
 #include <utility>
 
+#include <boost/array.hpp>
 #include <boost/assert.hpp>
 #include <boost/test/unit_test.hpp>
 #include <boost/utility.hpp>
@@ -18,7 +19,8 @@
 
 namespace ctx = boost::ctx;
 
-ctx::fcontext_t fcm, fc1, fc2;
+ctx::fcontext_t fcm;
+ctx::fcontext_t * fc = 0;
 int value1 = 0;
 std::string value2;
 double value3 = 0.;
@@ -26,25 +28,25 @@
 void f1( intptr_t)
 {
     ++value1;
-    ctx::jump_fcontext( & fc1, & fcm, 0);
+    ctx::jump_fcontext( fc, & fcm, 0);
 }
 
 void f3( intptr_t)
 {
     ++value1;
-    ctx::jump_fcontext( & fc1, & fcm, 0);
+    ctx::jump_fcontext( fc, & fcm, 0);
     ++value1;
-    ctx::jump_fcontext( & fc1, & fcm, 0);
+    ctx::jump_fcontext( fc, & fcm, 0);
 }
 
 void f4( intptr_t)
 {
-    ctx::jump_fcontext( & fc1, & fcm, 7);
+    ctx::jump_fcontext( fc, & fcm, 7);
 }
 
 void f5( intptr_t arg)
 {
-    ctx::jump_fcontext( & fc1, & fcm, arg);
+    ctx::jump_fcontext( fc, & fcm, arg);
 }
 
 void f6( intptr_t arg)
@@ -52,9 +54,9 @@
     std::pair< int, int > data = * ( std::pair< int, int > * ) arg;
     int res = data.first + data.second;
     data = * ( std::pair< int, int > *)
-        ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) res);
+        ctx::jump_fcontext( fc, & fcm, ( intptr_t) res);
     res = data.first + data.second;
-    ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) res);
+    ctx::jump_fcontext( fc, & fcm, ( intptr_t) res);
 }
 
 void f7( intptr_t arg)
@@ -63,7 +65,7 @@
     { throw std::runtime_error( ( char *) arg); }
     catch ( std::runtime_error const& e)
     { value2 = e.what(); }
-    ctx::jump_fcontext( & fc1, & fcm, arg);
+    ctx::jump_fcontext( fc, & fcm, arg);
 }
 
 void f8( intptr_t arg)
@@ -71,28 +73,34 @@
     double d = * ( double *) arg;
     d += 3.45;
     value3 = d;
-    ctx::jump_fcontext( & fc1, & fcm, 0);
+    ctx::jump_fcontext( fc, & fcm, 0);
 }
 
-void test_stack_utils()
+void test_setup()
 {
-    if ( ! ctx::stack_allocator::is_stack_unbound() )
-        BOOST_CHECK( ctx::stack_allocator::maximum_stacksize() >= ctx::stack_allocator::default_stacksize() );
-    BOOST_CHECK( ctx::stack_allocator::default_stacksize() >= ctx::stack_allocator::minimum_stacksize() );
+    ctx::guarded_stack_allocator alloc;
+
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f1);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size);
 }
 
 void test_start()
 {
     value1 = 0;
 
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
-    fc1.fc_stack.sp = alloc.allocate( ctx::stack_allocator::minimum_stacksize() );
-    fc1.fc_stack.size = ctx::stack_allocator::minimum_stacksize();
-    ctx::make_fcontext( & fc1, f1);
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f1);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size);
 
     BOOST_CHECK_EQUAL( 0, value1);
-    ctx::jump_fcontext( & fcm, & fc1, 0);
+    ctx::jump_fcontext( & fcm, fc, 0);
     BOOST_CHECK_EQUAL( 1, value1);
 }
 
@@ -100,83 +108,95 @@
 {
     value1 = 0;
 
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
-    fc1.fc_stack.sp = alloc.allocate( ctx::stack_allocator::minimum_stacksize() );
-    fc1.fc_stack.size = ctx::stack_allocator::minimum_stacksize();
-    ctx::make_fcontext( & fc1, f3);
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f3);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size);
 
     BOOST_CHECK_EQUAL( 0, value1);
-    ctx::jump_fcontext( & fcm, & fc1, 0);
+    ctx::jump_fcontext( & fcm, fc, 0);
     BOOST_CHECK_EQUAL( 1, value1);
-    ctx::jump_fcontext( & fcm, & fc1, 0);
+    ctx::jump_fcontext( & fcm, fc, 0);
     BOOST_CHECK_EQUAL( 2, value1);
 }
 
 void test_result()
 {
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
-    fc1.fc_stack.sp = alloc.allocate( ctx::stack_allocator::minimum_stacksize() );
-    fc1.fc_stack.size = ctx::stack_allocator::minimum_stacksize();
-    ctx::make_fcontext( & fc1, f4);
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f4);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size);
 
-    int result = ( int) ctx::jump_fcontext( & fcm, & fc1, 0);
+    int result = ( int) ctx::jump_fcontext( & fcm, fc, 0);
     BOOST_CHECK_EQUAL( 7, result);
 }
 
 void test_arg()
 {
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
-    fc1.fc_stack.sp = alloc.allocate( ctx::stack_allocator::minimum_stacksize() );
-    fc1.fc_stack.size = ctx::stack_allocator::minimum_stacksize();
     int i = 7;
-    ctx::make_fcontext( & fc1, f5);
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f5);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size);
 
-    int result = ( int) ctx::jump_fcontext( & fcm, & fc1, i);
+    int result = ( int) ctx::jump_fcontext( & fcm, fc, i);
     BOOST_CHECK_EQUAL( i, result);
 }
 
 void test_transfer()
 {
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
-    fc1.fc_stack.sp = alloc.allocate( ctx::stack_allocator::minimum_stacksize() );
-    fc1.fc_stack.size = ctx::stack_allocator::minimum_stacksize();
     std::pair< int, int > data = std::make_pair( 3, 7);
-    ctx::make_fcontext( & fc1, f6);
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f6);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size);
 
-    int result = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & data);
+    int result = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & data);
     BOOST_CHECK_EQUAL( 10, result);
     data = std::make_pair( 7, 7);
-    result = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & data);
+    result = ( int) ctx::jump_fcontext( & fcm, fc, ( intptr_t) & data);
     BOOST_CHECK_EQUAL( 14, result);
 }
 
 void test_exception()
 {
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
-    fc1.fc_stack.sp = alloc.allocate( ctx::stack_allocator::minimum_stacksize() );
-    fc1.fc_stack.size = ctx::stack_allocator::minimum_stacksize();
     const char * what = "hello world";
-    ctx::make_fcontext( & fc1, f7);
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::default_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::default_stacksize(), f7);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::default_stacksize(), fc->fc_stack.size);
 
-    ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) what);
+    ctx::jump_fcontext( & fcm, fc, ( intptr_t) what);
     BOOST_CHECK_EQUAL( std::string( what), value2);
 }
 
 void test_fp()
 {
-    ctx::stack_allocator alloc;
+    ctx::guarded_stack_allocator alloc;
 
-    fc1.fc_stack.sp = alloc.allocate( ctx::stack_allocator::minimum_stacksize() );
-    fc1.fc_stack.size = ctx::stack_allocator::minimum_stacksize();
     double d = 7.13;
-    ctx::make_fcontext( & fc1, f8);
+    void * sp = alloc.allocate( ctx::guarded_stack_allocator::minimum_stacksize() );
+    fc = ctx::make_fcontext( sp, ctx::guarded_stack_allocator::minimum_stacksize(), f8);
+    BOOST_CHECK( fc);
+    BOOST_CHECK_EQUAL( sp, fc->fc_stack.sp);
+    BOOST_CHECK_EQUAL( ctx::guarded_stack_allocator::minimum_stacksize(), fc->fc_stack.size);
 
-    ctx::jump_fcontext( & fcm, & fc1, (intptr_t) & d);
+    ctx::jump_fcontext( & fcm, fc, (intptr_t) & d);
     BOOST_CHECK_EQUAL( 10.58, value3);
 }
 
@@ -185,7 +205,7 @@
     boost::unit_test::test_suite * test =
         BOOST_TEST_SUITE("Boost.Context: context test suite");
 
-    test->add( BOOST_TEST_CASE( & test_stack_utils) );
+    test->add( BOOST_TEST_CASE( & test_setup) );
     test->add( BOOST_TEST_CASE( & test_start) );
     test->add( BOOST_TEST_CASE( & test_jump) );
     test->add( BOOST_TEST_CASE( & test_result) );