Boost logo

Boost-Commit :

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) );


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk