Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80338 - in trunk: 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-08-31 15:50:10


Author: olli
Date: 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
New Revision: 80338
URL: http://svn.boost.org/trac/boost/changeset/80338

Log:
context: new layout for fcontext_t
 - fcontext_t takes pointer to stack (lower addresses) and stack size
 - make_fcontext() computes start address of stack pointer depending on
   architecture (growing upwards, downwards)
 - make_fcontext() preserves frame pointer on intel
 - stack alignment corrected on intel
 - BOOST_USE_UCONTEXT for performance measurements added

Removed:
   trunk/libs/context/doc/config.qbk
Text files modified:
   trunk/boost/context/detail/fcontext_arm.hpp | 4
   trunk/boost/context/detail/fcontext_i386.hpp | 4
   trunk/boost/context/detail/fcontext_i386_win.hpp | 6
   trunk/boost/context/detail/fcontext_mips.hpp | 4
   trunk/boost/context/detail/fcontext_ppc.hpp | 4
   trunk/boost/context/detail/fcontext_x86_64.hpp | 4
   trunk/boost/context/detail/fcontext_x86_64_win.hpp | 6
   trunk/libs/context/build/Jamfile.v2 | 241 +++++++++++++++++++++++++++++----------
   trunk/libs/context/doc/fcontext.qbk | 7
   trunk/libs/context/doc/performance.qbk | 3
   trunk/libs/context/doc/requirements.qbk | 8
   trunk/libs/context/doc/stack.qbk | 12 +
   trunk/libs/context/example/exit.cpp | 4
   trunk/libs/context/example/jump.cpp | 4
   trunk/libs/context/example/transfer.cpp | 2
   trunk/libs/context/performance/performance.cpp | 122 +++++++++----------
   trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S | 4
   trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm | 61 +++++----
   trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S | 52 ++++---
   trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S | 45 ++++---
   trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S | 4
   trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S | 4
   trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S | 4
   trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm | 56 ++++----
   trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S | 51 +++++---
   trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S | 51 +++++---
   trunk/libs/context/src/stack_allocator_posix.cpp | 15 +-
   trunk/libs/context/src/stack_allocator_windows.cpp | 17 +-
   trunk/libs/context/src/stack_utils_posix.cpp | 48 +++++--
   trunk/libs/context/src/stack_utils_windows.cpp | 57 +++++---
   trunk/libs/context/test/test_context.cpp | 22 ++-
   31 files changed, 573 insertions(+), 353 deletions(-)

Modified: trunk/boost/context/detail/fcontext_arm.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_arm.hpp (original)
+++ trunk/boost/context/detail/fcontext_arm.hpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -27,11 +27,11 @@
 
 struct stack_t
 {
- void * base;
+ void * sp;
     std::size_t size;
 
     stack_t() :
- base( 0), size( 0)
+ sp( 0), size( 0)
     {}
 };
 

Modified: trunk/boost/context/detail/fcontext_i386.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_i386.hpp (original)
+++ trunk/boost/context/detail/fcontext_i386.hpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -27,11 +27,11 @@
 
 struct stack_t
 {
- void * base;
+ void * sp;
     std::size_t size;
 
     stack_t() :
- base( 0), size( 0)
+ sp( 0), size( 0)
     {}
 };
 

Modified: trunk/boost/context/detail/fcontext_i386_win.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_i386_win.hpp (original)
+++ trunk/boost/context/detail/fcontext_i386_win.hpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -36,12 +36,12 @@
 
 struct stack_t
 {
- void * base;
- void * limit;
+ void * sp;
     std::size_t size;
+ void * limit;
 
     stack_t() :
- base( 0), limit( 0), size( 0)
+ sp( 0), size( 0), limit( 0)
     {}
 };
 

Modified: trunk/boost/context/detail/fcontext_mips.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_mips.hpp (original)
+++ trunk/boost/context/detail/fcontext_mips.hpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -29,11 +29,11 @@
 
 struct stack_t
 {
- void * base;
+ void * sp;
     std::size_t size;
 
     stack_t() :
- base( 0), size( 0)
+ sp( 0), size( 0)
     {}
 };
 

Modified: trunk/boost/context/detail/fcontext_ppc.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_ppc.hpp (original)
+++ trunk/boost/context/detail/fcontext_ppc.hpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -27,11 +27,11 @@
 
 struct stack_t
 {
- void * base;
+ void * sp;
     std::size_t size;
 
     stack_t() :
- base( 0), size( 0)
+ sp( 0), size( 0)
     {}
 };
 

Modified: trunk/boost/context/detail/fcontext_x86_64.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_x86_64.hpp (original)
+++ trunk/boost/context/detail/fcontext_x86_64.hpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -27,11 +27,11 @@
 
 struct stack_t
 {
- void * base;
+ void * sp;
     std::size_t size;
 
     stack_t() :
- base( 0), size( 0)
+ sp( 0), size( 0)
     {}
 };
 

Modified: trunk/boost/context/detail/fcontext_x86_64_win.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_x86_64_win.hpp (original)
+++ trunk/boost/context/detail/fcontext_x86_64_win.hpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -36,12 +36,12 @@
 
 struct stack_t
 {
- void * base;
- void * limit;
+ void * sp;
     std::size_t size;
+ void * limit;
 
     stack_t() :
- base( 0), limit( 0), size( 0)
+ sp( 0), size( 0), limit( 0)
     {}
 };
 

Modified: trunk/libs/context/build/Jamfile.v2
==============================================================================
--- trunk/libs/context/build/Jamfile.v2 (original)
+++ trunk/libs/context/build/Jamfile.v2 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -23,255 +23,374 @@
       <link>shared:<define>BOOST_CONTEXT_DYN_LINK=1
     ;
 
+local rule default_binary_format ( )
+{
+ local tmp = elf ;
+ if [ os.name ] = "MACOSX" { tmp = mach-o ; }
+ if [ os.name ] = "NT" { tmp = pe ; }
+ return $(tmp) ;
+}
+
+feature.feature binary-format
+ : elf
+ mach-o
+ pe
+ : propagated
+ ;
+feature.set-default binary-format : [ default_binary_format ] ;
+
+
+local rule default_abi ( )
+{
+ local tmp = sysv ;
+ if [ os.name ] = "NT" { tmp = ms ; }
+ else if [ os.platform ] = "ARM" { tmp = aapcs ; }
+ else if [ os.platform ] = "MIPS" { tmp = o32 ; }
+ return $(tmp) ;
+}
+
+feature.feature abi
+ : aapcs
+ eabi
+ ms
+ n32
+ n64
+ o32
+ o64
+ sysv
+ : propagated
+ ;
+feature.set-default abi : [ default_abi ] ;
+
 
 actions gas
 {
- as -o "$(<)" "$(>)"
+ as -o "$(<)" "$(>)"
 }
 
 actions masm
 {
- ml /c /Fo"$(<)" "$(>)"
+ ml /c /Fo"$(<)" "$(>)"
 }
 
 actions masm64
 {
- ml64 /c /Fo"$(<)" "$(>)"
+ ml64 /c /Fo"$(<)" "$(>)"
 }
 
 
 rule configure ( properties * )
 {
- local result ;
+ local result ;
+
+# if ( ! ( <toolset>gcc in $(properties)
+# || <toolset>intel in $(properties)
+# || <toolset>msvc in $(properties) ) )
+# {
+# result = <build>no ;
+# ECHO "toolset not supported" ;
+# }
 
- return $(result) ;
+ return $(result) ;
 }
 
 # ARM
 alias asm_context_sources
    : asm/fcontext_arm_aapcs_elf_gas.S
- : <architecture>arm
- <toolset>gcc
+ : <abi>aapcs
+ <architecture>arm
+ <binary-format>elf
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_arm_aapcs_elf_gas.S
- : <architecture>arm
- <toolset>qcc
+ : <abi>aapcs
+ <architecture>arm
+ <binary-format>elf
+ <toolset>qcc
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_arm_aapcs_elf_gas.o : asm/fcontext_arm_aapcs_elf_gas.S : @gas ]
- : <architecture>arm
+ : <abi>aapcs
+ <architecture>arm
+ <binary-format>elf
    ;
 
 # MIPS 32bit
 alias asm_context_sources
    : asm/fcontext_mips32_o32_elf_gas.S
- : <architecture>mips1
- <toolset>gcc
+ : <abi>o32
+ <architecture>mips1
+ <binary-format>elf
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_mips32_o32_elf_gas.S
- : <architecture>mips1
- <toolset>qcc
+ : <abi>o32
+ <architecture>mips1
+ <binary-format>elf
+ <toolset>qcc
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_mips32_o32_elf_gas.o : asm/fcontext_mips32_o32_elf_gas.S : @gas ]
- : <architecture>mips1
+ : <abi>o32
+ <architecture>mips1
+ <binary-format>elf
    ;
 
 # POWERPC 32bit
 alias asm_context_sources
    : asm/fcontext_ppc32_sysv_elf_gas.S
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>power
- <toolset>gcc
+ <binary-format>elf
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_ppc32_sysv_elf_gas.S
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>power
- <toolset>qcc
+ <binary-format>elf
+ <toolset>qcc
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_ppc32_sysv_elf_gas.o : asm/fcontext_ppc32_sysv_elf_gas.S : @gas ]
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>power
+ <binary-format>elf
    ;
 
 # POWERPC 64bit
 alias asm_context_sources
    : asm/fcontext_ppc64_sysv_elf_gas.S
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>power
- <toolset>gcc
+ <binary-format>elf
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_ppc64_sysv_elf_gas.S
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>power
- <toolset>qcc
+ <binary-format>elf
+ <toolset>qcc
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_ppc64_sysv_elf_gas.o : asm/fcontext_ppc64_sysv_elf_gas.S : @gas ]
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>power
+ <binary-format>elf
    ;
 
 # I386
 alias asm_context_sources
    : asm/fcontext_i386_sysv_elf_gas.S
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>x86
- <toolset>gcc
+ <binary-format>elf
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_i386_sysv_elf_gas.S
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>x86
- <toolset>qcc
+ <binary-format>elf
+ <toolset>qcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_i386_sysv_elf_gas.S
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>x86
- <toolset>intel
+ <binary-format>elf
+ <toolset>intel
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_i386_sysv_elf_gas.o : asm/fcontext_i386_sysv_elf_gas.S : @gas ]
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
+ <architecture>x86
+ <binary-format>elf
+ ;
+
+alias asm_context_sources
+ : asm/fcontext_i386_sysv_macho_gas.S
+ : <abi>sysv
+ <address-model>32
      <architecture>x86
+ <binary-format>mach-o
+ <target-os>darwin
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_i386_sysv_macho_gas.S
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>x86
+ <binary-format>mach-o
      <target-os>darwin
- <toolset>gcc
+ <toolset>qcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_i386_sysv_macho_gas.S
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>x86
+ <binary-format>mach-o
      <target-os>darwin
- <toolset>intel
+ <toolset>intel
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_i386_sysv_macho_gas.o : asm/fcontext_i386_sysv_macho_gas.S : @gas ]
- : <address-model>32
+ : <abi>sysv
+ <address-model>32
      <architecture>x86
+ <binary-format>mach-o
      <target-os>darwin
    ;
 
 alias asm_context_sources
    : asm/fcontext_i386_ms_pe_masm.asm
- : <address-model>32
+ : <abi>ms
+ <address-model>32
      <architecture>x86
+ <binary-format>pe
      <target-os>windows
- <toolset>intel
+ <toolset>intel
    ;
 
 alias asm_context_sources
    : asm/fcontext_i386_ms_pe_masm.asm
- : <address-model>32
+ : <abi>ms
+ <address-model>32
      <architecture>x86
+ <binary-format>pe
      <target-os>windows
- <toolset>msvc
+ <toolset>msvc
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_i386_ms_pe_masm.o : asm/fcontext_i386_ms_pe_masm.asm : @masm ]
- : <address-model>32
+ : <abi>ms
+ <address-model>32
      <architecture>x86
+ <binary-format>pe
      <target-os>windows
    ;
 
-
 # X86_64
 alias asm_context_sources
    : asm/fcontext_x86_64_sysv_elf_gas.S
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>x86
- <toolset>gcc
+ <binary-format>elf
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_x86_64_sysv_elf_gas.S
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>x86
- <toolset>qcc
+ <binary-format>elf
+ <toolset>qcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_x86_64_sysv_elf_gas.S
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>x86
- <toolset>intel
+ <binary-format>elf
+ <toolset>intel
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_x86_64_sysv_elf_gas.o : asm/fcontext_x86_64_sysv_elf_gas.S : @gas ]
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>x86
+ <binary-format>elf
    ;
 
-
 alias asm_context_sources
    : asm/fcontext_x86_64_sysv_macho_gas.S
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>x86
+ <binary-format>mach-o
      <target-os>darwin
- <toolset>gcc
+ <toolset>gcc
    ;
 
 alias asm_context_sources
    : asm/fcontext_x86_64_sysv_macho_gas.S
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>x86
+ <binary-format>mach-o
      <target-os>darwin
- <toolset>intel
+ <toolset>intel
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_x86_64_sysv_macho_gas.o : asm/fcontext_x86_64_sysv_macho_gas.S : @gas ]
- : <address-model>64
+ : <abi>sysv
+ <address-model>64
      <architecture>x86
+ <binary-format>mach-o
      <target-os>darwin
    ;
 
 alias asm_context_sources
    : asm/fcontext_x86_64_ms_pe_masm.asm
- : <address-model>64
+ : <abi>ms
+ <address-model>64
      <architecture>x86
+ <binary-format>pe
      <target-os>windows
- <toolset>intel
+ <toolset>intel
    ;
 
 alias asm_context_sources
    : asm/fcontext_x86_64_ms_pe_masm.asm
- : <address-model>64
+ : <abi>ms
+ <address-model>64
      <architecture>x86
+ <binary-format>pe
      <target-os>windows
- <toolset>msvc
+ <toolset>msvc
    ;
 
 alias asm_context_sources
    : [ make asm/fcontext_x86_64_ms_pe_masm.o : asm/fcontext_x86_64_ms_pe_masm.asm : @masm64 ]
- : <address-model>64
+ : <abi>ms
+ <address-model>64
      <architecture>x86
+ <binary-format>pe
      <target-os>windows
    ;
 

Deleted: trunk/libs/context/doc/config.qbk
==============================================================================
--- trunk/libs/context/doc/config.qbk 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
+++ (empty file)
@@ -1,60 +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
-]
-
-[section:installtion How to build and install]
-
-__boost_context__ must be built for the particular compiler(s) and CPU architecture(s)s
-being targeted. __boost_context__ includes assembly code and, therefore, requires
-GNU AS for supported POSIX systems, and MASM for Windows systems.
-
-[note The architecture, instruction set, and address model are optional __boost_build__
-properties that must be given on the bjam command line, as shown in the table below.]
-
-[table
- [[][]]
- [
- [ARM, UNIX, aapcs, elf]
- [bjam toolset = gcc architecture = arm]
- ]
- [
- [MIPS (32bit), UNIX, o32, elf]
- [bjam toolset = gcc architecture = mips1]
- ]
- [
- [I386, UNIX, sysv, elf]
- [bjam toolset = gcc architecture = x86 instruction-set = i686 address-model = 32]
- ]
- [
- [I386, UNIX, sysv, elf]
- [bjam toolset = intel architecture = x86 instruction-set = i686 address-model = 32]
- ]
- [
- [I386, Windows, ms, pe]
- [bjam toolset = msvc-9.0 architecture = x86 instruction-set = i686 address-model = 32]
- ]
- [
- [PowerPc (32bit), UNIX, sysv, elf]
- [bjam toolset = gcc architecture = power address-model = 32]
- ]
- [
- [PowerPc (64bit), UNIX, sysv, elf]
- [bjam toolset = gcc architecture = power address-model = 64]
- ]
- [
- [X86_64, UNIX, sysv, elf]
- [bjam toolset = gcc architecture = x86 instruction-set = yorksfield address-model = 64]
- ]
- [
- [X86_64, UNIX, sysv, elf]
- [bjam toolset = intel architecture = x86 instruction-set = yorksfield address-model = 64]
- ]
- [
- [X86_64, Windows, ms, pe]
- [bjam toolset = msvc-10.0 architecture = x86 instruction-set = yorksfield address-model = 64]
- ]
-]
-[endsect]

Modified: trunk/libs/context/doc/fcontext.qbk
==============================================================================
--- trunk/libs/context/doc/fcontext.qbk (original)
+++ trunk/libs/context/doc/fcontext.qbk 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -11,7 +11,8 @@
 space). Together with its related functions __jump_fcontext__ and
 __make_fcontext__ it provides a execution control transfer mechanism similar
 interface like
-[@http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html ucontext_t].
+[@http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html
+ucontext_t].
 __fcontext__ and its functions are located in __context_ns__ and the functions
 are declared as extern "C".
 
@@ -40,8 +41,8 @@
             // context fc uses f() as context function
             make_fcontext( & fc, f);
 
-__fcontext__ requires a pointer to the top of the stack (__fc_base__) as well
-as the size of the stack.
+__fcontext__ requires a pointer (__fc_base__) as well as the size of the
+stack.
 
 Calling __jump_fcontext__ invokes the __context_fn__ in a newly created context
 complete with registers, flags, stack and instruction pointers. When control

Modified: trunk/libs/context/doc/performance.qbk
==============================================================================
--- trunk/libs/context/doc/performance.qbk (original)
+++ trunk/libs/context/doc/performance.qbk 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -14,6 +14,9 @@
 to a single CPU. The code was compiled using the build options,
 'variant = release cxxflags = -DBOOST_DISABLE_ASSERTS'.
 
+Applying `-DBOOST_USE_UCONTEXT` to cxxflags the performance of `ucontext` will
+be measured too.
+
 The numbers in the table are the number of cycles per iteration, based upon an
 average computed over 10 iterations.
 

Modified: trunk/libs/context/doc/requirements.qbk
==============================================================================
--- trunk/libs/context/doc/requirements.qbk (original)
+++ trunk/libs/context/doc/requirements.qbk 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -12,7 +12,11 @@
 therefore, requires GNU AS for supported POSIX systems, and MASM for Windows
 systems.
 
-[important Please note that address-model=64 must be given to bjam command line
-on 64bit Windows (boost-build issue).]
+[important Please note that `address-model=64` must be given to bjam command line
+on 64bit Windows for 64bit build; otherwise 32bit code will be generated.]
+
+[important For cross-compiling the lib you must specify certain additional
+properties at bjam command line: `target-os`, `abi`, `binary-format`,
+`architecture` and `address-model`.]
 
 [endsect]

Modified: trunk/libs/context/doc/stack.qbk
==============================================================================
--- trunk/libs/context/doc/stack.qbk (original)
+++ trunk/libs/context/doc/stack.qbk 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -50,9 +50,9 @@
 
 __boost_context__ provides a __stack_allocator__ `stack_allocator` which models
 the __stack_allocator_concept__ concept.
-It appends a __guard_page__ 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.
+It creates a __guard_page__ at the end of the 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.
 
 [endsect]
 
@@ -77,12 +77,14 @@
 [heading `std::size_t default_stacksize()`]
 [variablelist
 [[Returns:] [Returns a default stack size, which may be platform specific.
-The present implementation returns a value of 256 kB.]]
+If the stack is unbound then the present implementation returns the maximum of
+`256 kB` and `minimum_stacksize()`.]]
 ]
 
 [heading `std::size_t minimum_stacksize()`]
 [variablelist
-[[Returns:] [Returns the minimum size in bytes of stack defined by the environment.]]
+[[Returns:] [Returns the minimum size in bytes of stack defined by the
+environment plus a pagesize (guard page).]]
 [[Throws:] [Nothing.]]
 ]
 

Modified: trunk/libs/context/example/exit.cpp
==============================================================================
--- trunk/libs/context/example/exit.cpp (original)
+++ trunk/libs/context/example/exit.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -37,11 +37,11 @@
         ctx::fcontext_t fcm;
         ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
         fc1.fc_stack.size = ctx::minimum_stacksize();
         ctx::make_fcontext( & fc1, f1);
 
- fc2.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc2.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
         fc2.fc_stack.size = ctx::minimum_stacksize();
         ctx::make_fcontext( & fc2, f2);
 

Modified: trunk/libs/context/example/jump.cpp
==============================================================================
--- trunk/libs/context/example/jump.cpp (original)
+++ trunk/libs/context/example/jump.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -37,11 +37,11 @@
 {
         ctx::stack_allocator alloc1, alloc2;
 
- fc1.fc_stack.base = alloc1.allocate(ctx::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.base = alloc2.allocate(ctx::minimum_stacksize());
+ fc2.fc_stack.sp = alloc2.allocate(ctx::minimum_stacksize());
         fc2.fc_stack.size = ctx::minimum_stacksize();
         ctx::make_fcontext( & fc2, f2);
 

Modified: trunk/libs/context/example/transfer.cpp
==============================================================================
--- trunk/libs/context/example/transfer.cpp (original)
+++ trunk/libs/context/example/transfer.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -32,7 +32,7 @@
 {
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.sp = alloc.allocate(ctx::minimum_stacksize());
     fc1.fc_stack.size = ctx::minimum_stacksize();
     ctx::make_fcontext( & fc1, f1);
 

Modified: trunk/libs/context/performance/performance.cpp
==============================================================================
--- trunk/libs/context/performance/performance.cpp (original)
+++ trunk/libs/context/performance/performance.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -19,7 +19,7 @@
 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/program_options.hpp>
 
-#ifndef BOOST_WINDOWS
+#ifdef BOOST_USE_UCONTEXT
 #include <ucontext.h>
 #endif
 
@@ -32,48 +32,51 @@
 
 namespace ctx = boost::ctx;
 
-bool preserve_fpu = false;
+bool pres_fpu = false;
 
-#define CALL_FUNCTION(z,n,unused) \
- fn();
+#define CALL_FCONTEXT(z,n,unused) ctx::jump_fcontext( & fcm, & fc, 7, pres_fpu);
 
-#define CALL_UCONTEXT(z,n,unused) \
- ::swapcontext( & ucm, & uc);
+#ifdef BOOST_USE_UCONTEXT
+# define CALL_UCONTEXT(z,n,unused) ::swapcontext( & ucm, & uc);
+#endif
+
+#define CALL_FUNCTION(z,n,unused) fn();
 
-#define CALL_FCONTEXT(z,n,unused) \
- ctx::jump_fcontext( & fcm, & fc, 7, preserve_fpu);
 
-#ifndef BOOST_WINDOWS
+ctx::fcontext_t fc, fcm;
+
+#ifdef BOOST_USE_UCONTEXT
 ucontext_t uc, ucm;
 #endif
-ctx::fcontext_t fc, fcm;
 
-static void f3()
-{ }
 
-#ifndef BOOST_WINDOWS
+static void f1( intptr_t)
+{ while ( true) ctx::jump_fcontext( & fc, & fcm, 7, pres_fpu); }
+
+#ifdef BOOST_USE_UCONTEXT
 static void f2()
-{
- while ( true)
- ::swapcontext( & uc, & ucm);
-}
+{ while ( true) ::swapcontext( & uc, & ucm); }
 #endif
 
-static void f1( intptr_t)
-{
- while ( true)
- ctx::jump_fcontext( & fc, & fcm, 7, preserve_fpu);
-}
+static void f3()
+{}
+
 
 #ifdef BOOST_CONTEXT_CYCLE
-cycle_t test_function_cycle( cycle_t ov)
+cycle_t test_fcontext_cycle( cycle_t ov)
 {
- boost::function< void() > fn( boost::bind( f3) );
+ 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::jump_fcontext( & fcm, & fc, 7, pres_fpu);
+
     // cache warum-up
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
 
     cycle_t start( cycles() );
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
     cycle_t total( cycles() - start);
 
     // we have two jumps and two measuremt-overheads
@@ -84,15 +87,13 @@
     return total;
 }
 
-#ifndef BOOST_WINDOWS
+# ifdef BOOST_USE_UCONTEXT
 cycle_t test_ucontext_cycle( cycle_t ov)
 {
     ctx::stack_allocator alloc;
 
     ::getcontext( & uc);
- uc.uc_stack.ss_sp =
- static_cast< char * >( alloc.allocate(ctx::default_stacksize() ) )
- - ctx::default_stacksize();
+ uc.uc_stack.ss_sp = alloc.allocate(ctx::default_stacksize());
     uc.uc_stack.ss_size = ctx::default_stacksize();
     ::makecontext( & uc, f2, 7);
 
@@ -110,22 +111,16 @@
 
     return total;
 }
-#endif
+# endif
 
-cycle_t test_fcontext_cycle( cycle_t ov)
+cycle_t test_function_cycle( cycle_t ov)
 {
- ctx::stack_allocator alloc;
- fc.fc_stack.base = alloc.allocate(ctx::default_stacksize());
- fc.fc_stack.size = ctx::default_stacksize();
- ctx::make_fcontext( & fc, f1);
-
- ctx::jump_fcontext( & fcm, & fc, 7, preserve_fpu);
-
+ boost::function< void() > fn( boost::bind( f3) );
     // cache warum-up
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
 
     cycle_t start( cycles() );
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
     cycle_t total( cycles() - start);
 
     // we have two jumps and two measuremt-overheads
@@ -137,15 +132,22 @@
 }
 #endif
 
+
 #if _POSIX_C_SOURCE >= 199309L
-zeit_t test_function_zeit( zeit_t ov)
+zeit_t test_fcontext_zeit( zeit_t ov)
 {
- boost::function< void() > fn( boost::bind( f3) );
+ 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::jump_fcontext( & fcm, & fc, 7, pres_fpu);
+
     // cache warum-up
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
 
     zeit_t start( zeit() );
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
     zeit_t total( zeit() - start);
 
     // we have two jumps and two measuremt-overheads
@@ -156,15 +158,13 @@
     return total;
 }
 
-#ifndef BOOST_WINDOWS
+# ifdef BOOST_USE_UCONTEXT
 zeit_t test_ucontext_zeit( zeit_t ov)
 {
     ctx::stack_allocator alloc;
 
     ::getcontext( & uc);
- uc.uc_stack.ss_sp =
- static_cast< char * >( alloc.allocate(ctx::default_stacksize() ) )
- - ctx::default_stacksize();
+ uc.uc_stack.ss_sp = alloc.allocate(ctx::default_stacksize());
     uc.uc_stack.ss_size = ctx::default_stacksize();
     ::makecontext( & uc, f2, 7);
 
@@ -182,22 +182,16 @@
 
     return total;
 }
-#endif
+# endif
 
-zeit_t test_fcontext_zeit( zeit_t ov)
+zeit_t test_function_zeit( zeit_t ov)
 {
- ctx::stack_allocator alloc;
- fc.fc_stack.base = alloc.allocate(ctx::default_stacksize());
- fc.fc_stack.size = ctx::default_stacksize();
- ctx::make_fcontext( & fc, f1);
-
- ctx::jump_fcontext( & fcm, & fc, 7, preserve_fpu);
-
+ boost::function< void() > fn( boost::bind( f3) );
     // cache warum-up
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
 
     zeit_t start( zeit() );
-BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~)
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~)
     zeit_t total( zeit() - start);
 
     // we have two jumps and two measuremt-overheads
@@ -222,10 +216,10 @@
 
             unsigned int res = test_fcontext_cycle( ov);
             std::cout << "fcontext: average of " << res << " cycles per switch" << std::endl;
-#ifndef BOOST_WINDOWS
+# ifdef BOOST_USE_UCONTEXT
             res = test_ucontext_cycle( ov);
             std::cout << "ucontext: average of " << res << " cycles per switch" << std::endl;
-#endif
+# endif
             res = test_function_cycle( ov);
             std::cout << "boost::function: average of " << res << " cycles per switch" << std::endl;
         }
@@ -238,10 +232,10 @@
 
             unsigned int res = test_fcontext_zeit( ov);
             std::cout << "fcontext: average of " << res << " ns per switch" << std::endl;
-#ifndef BOOST_WINDOWS
+# ifdef BOOST_USE_UCONTEXT
             res = test_ucontext_zeit( ov);
             std::cout << "ucontext: average of " << res << " ns per switch" << std::endl;
-#endif
+# endif
             res = test_function_zeit( ov);
             std::cout << "boost::function: average of " << res << " ns per switch" << std::endl;
         }

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -26,7 +26,7 @@
  * ------------------------------------------------------------- *
  * | 0x2c| 0x30| | *
  * ------------------------------------------------------------- *
- * |sbase|slimit| | *
+ * | sp | size| | *
  * ------------------------------------------------------------- *
  * ------------------------------------------------------------- *
  * | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | *
@@ -79,6 +79,8 @@
 make_fcontext:
     str a2, [a1,#40] @ save address of context function
     ldr a2, [a1,#44] @ load address of context stack base
+ ldr a3, [a1,#48] @ load size of context stack
+ add a2, a3 @ compute start address of context stack
 
     push {a1,lr} @ save pointer to fcontext_t
     mov a1, a2 @ context stack pointer as arg for align_stack

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -16,7 +16,7 @@
 ; --------------------------------------------------------------
 ; | 018h | 01ch | 020h | |
 ; --------------------------------------------------------------
-; | base | limit | size | |
+; | sp | size | base | |
 ; --------------------------------------------------------------
 ; --------------------------------------------------------------
 ; | 9 | |
@@ -61,9 +61,9 @@
     mov eax, [edx] ; load current SEH exception list
     mov [ecx+024h], eax ; save current exception list
     mov eax, [edx+04h] ; load current stack base
- mov [ecx+018h], eax ; save current stack base
+ mov [ecx+020h], eax ; save current stack base
     mov eax, [edx+08h] ; load current stack limit
- mov [ecx+01ch], eax ; save current stack limit
+ mov [ecx+018h], eax ; save current stack limit
     mov eax, [edx+010h] ; load fiber local storage
     mov [ecx+028h], eax ; save fiber local storage
 
@@ -93,9 +93,9 @@
     assume fs:error
     mov eax, [ecx+024h] ; load SEH exception list
     mov [edx], eax ; restore next SEH item
- mov eax, [ecx+018h] ; load stack base
+ mov eax, [ecx+020h] ; load stack base
     mov [edx+04h], eax ; restore stack base
- mov eax, [ecx+01ch] ; load stack limit
+ mov eax, [ecx+018h] ; load stack limit
     mov [edx+08h], eax ; restore stack limit
     mov eax, [ecx+028h] ; load fiber local storage
     mov [edx+010h], eax ; restore fiber local storage
@@ -110,44 +110,51 @@
 jump_fcontext ENDP
 
 make_fcontext PROC EXPORT
- mov eax, [esp+04h] ; load address of the fcontext_t
- mov ecx, [esp+08h] ; load address of the context function
- mov [eax+014h], ecx ; save address of the context function
- mov edx, [eax+018h] ; load address of context stack base
- mov ecx, [eax+020h] ; load context stack size
- neg ecx ; negate stacksize for LEA
- lea ecx, [edx+ecx] ; compute context stack limit
- mov [eax+01ch], ecx ; save context stack limit
+ push ebp ; save previous frame pointer; get the stack 16 byte aligned
+ 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 (limit)
+ mov ecx, [eax+01ch] ; load context stack size
+ lea edx, [edx+ecx] ; compute top address of context stack (base)
+ mov [eax+020h], edx ; save top address of context stack (base)
 
- push eax ; save pointer to fcontext_t
- push edx ; context stack as arg for align_stack
+ 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
- pop eax ; remove arg for align_stack
- pop eax ; restore pointer to fcontext_t
+ mov eax, [esp+04h] ; restore pointer to fcontext_t
+
+ stmxcsr [eax+02ch] ; save MMX control word
+ fnstcw [eax+030h] ; save x87 control word
 
- lea edx, [edx-014h] ; reserve space for last frame on context stack, (ESP + 4) & 15 == 0
- mov [eax+010h], edx ; save the aligned stack
+ 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
 
     mov ecx, seh_fcontext ; set ECX to exception-handler
- mov [edx+0ch], ecx ; save ECX as SEH handler
+ mov [edx+018h], ecx ; save ECX as SEH handler
     mov ecx, 0ffffffffh ; set ECX to -1
- mov [edx+08h], ecx ; save ECX as next SEH item
- lea ecx, [edx+08h] ; load address of next SEH item
+ mov [edx+014h], ecx ; save ECX as next SEH item
+ lea ecx, [edx+014h] ; load address of next SEH item
     mov [eax+024h], ecx ; save next SEH
 
- stmxcsr [eax+02ch] ; save MMX control word
- fnstcw [eax+030h] ; save x87 control word
+ mov ecx, finish ; abs address of finish
+ mov [edx], ecx ; save address of finish as return address for context function
+ ; entered after context function returns
 
- mov ecx, finish ; address of finish
- mov [edx], ecx
+ add esp, 010h ; deallocate stack space
+ pop ebp
 
     xor eax, eax
     ret
 
 finish:
+ ; ESP == stack pointer of context function + 0x4
     xor eax, eax
- push eax ; exit code is zero
+ mov [esp], eax ; exit code is zero
     call _exit ; exit application
     hlt
 make_fcontext ENDP

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -19,7 +19,7 @@
  * -------------------------------------------------------------- *
  * | 0x18 | 0x1c | | *
  * -------------------------------------------------------------- *
- * | sbase | slimit | | *
+ * | sp | size | | *
  * -------------------------------------------------------------- *
  * -------------------------------------------------------------- *
  * | 8 | 9 | | *
@@ -76,46 +76,54 @@
 .align 2
 .type make_fcontext,@function
 make_fcontext:
- movl 0x4(%esp), %eax /* load address of the fcontext_t */
- movl 0x8(%esp), %ecx /* load address of the context function */
- movl %ecx, 0x14(%eax) /* save address of the context function */
+ pushl %ebp /* save previous frame pointer; get the stack 16 byte aligned */
+ 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 0x1c(%eax), %ecx /* load size of context stack */
+ leal (%edx,%ecx), %edx /* compute top address of context stack */
 
- pushl %eax /* save pointer to fcontext_t */
- pushl %ebx /* save EBX */
- pushl %edx /* context stack pointer as arg for align_stack */
+ 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 */
     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 */
- popl %eax /* remove arg for align_stack */
- popl %ebx /* restore EBX */
- popl %eax /* restore pointer to fcontext_t */
-
- leal -0x14(%edx), %edx /* reserve space for the last frame on context stack, (ESP + 4) % 16 == 0 */
- movl %edx, 0x10(%eax) /* save the aligned context stack base */
+ movl 0x4(%esp), %eax /* restore pointer to fcontext_t */
+ movl 0x8(%esp), %ebx /* restore EBX */
 
     stmxcsr 0x20(%eax) /* save MMX control and status word */
     fnstcw 0x24(%eax) /* save x87 control word */
 
- call 2f
-2: popl %ecx /* address of label 2 */
- addl $finish-2b, %ecx /* helper code executed after context function returns */
- movl %ecx, (%edx)
+ leal -0xc(%edx), %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
+2: popl %ecx /* address of label 2 */
+ addl $finish-2b, %ecx /* compute abs address of label finish */
+ movl %ecx, (%edx) /* save address of finish as return address for context functions */
+ /* entered after context function returns */
 
- xorl %eax, %eax
+ addl $0x10, %esp /* deallocate stack space */
+ pop %ebp
+
+ xorl %eax, %eax
     ret
 
 finish:
- leal -0xc(%esp), %esp
-
+ /* ESP == stack pointer of context function + 0x4 */
     call 3f
 3: popl %ebx /* address of label 3 */
     addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx /* compute address of GOT and store it in EBX */
 
- xorl %eax, %eax
- pushl %eax /* exit code is zero */
+ xorl %eax, %eax
+ movl %eax, (%esp) /* exit code is zero */
     call _exit_at_PLT /* exit application */
     hlt
 .size make_fcontext,.-make_fcontext

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -19,7 +19,7 @@
  * -------------------------------------------------------------- *
  * | 0x18 | 0x1c | | *
  * -------------------------------------------------------------- *
- * | sbase | slimit | | *
+ * | sp | size | | *
  * -------------------------------------------------------------- *
  * -------------------------------------------------------------- *
  * | 8 | 9 | | *
@@ -73,37 +73,44 @@
 .globl _make_fcontext
 .align 2
 _make_fcontext:
- movl 0x4(%esp), %eax /* load address of the fcontext_t */
- movl 0x8(%esp), %ecx /* load address of the context function */
- movl %ecx, 0x14(%eax) /* save address of the context function */
+ pushl %ebp /* save previous frame pointer; get the stack 16 byte aligned */
+ 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 0x1c(%eax), %ecx /* load size of context stack */
+ leal (%edx,%ecx), %edx /* compute top address of context stack */
 
- pushl %eax /* save pointer to fcontext_t */
- pushl %ebx /* save EBX */
- pushl %edx /* context stack pointer as arg for align_stack */
+ 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 */
- popl %eax /* remove arg for align_stack */
- popl %ebx /* restore EBX */
- popl %eax /* restore pointer to fcontext_t */
-
- leal -0x14(%edx), %edx /* reserve space for the last frame on context stack, (ESP + 4) % 16 == 0 */
- movl %edx, 0x10(%eax) /* save the aligned context stack base */
+ movl 0x4(%esp), %eax /* restore pointer to 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 */
+ movl %edx, 0x10(%eax) /* save address in EDX as stack pointer for context function */
+
     call 1f
-1: popl %ecx /* address of lable 1 */
- addl $finish-1b, %ecx /* helper code executed after context function returns */
- movl %ecx, (%edx)
+1: popl %ecx /* address of label 1 */
+ addl $finish-1b, %ecx /* compute abs address of label finish */
+ movl %ecx, (%edx) /* save address of finish as return address for context function */
+ /* entered after context function returns */
+
+ addl $0x10, %esp /* deallocate stack space */
+ pop %ebp
 
     xorl %eax, %eax
     ret
 
 finish:
- leal -0xc(%esp), %esp
- xorl %eax, %eax
- pushl %eax /* exit code is zero */
+ /* ESP == stack pointer of context function + 0x4 */
+ xorl %eax, %eax
+ movl %eax, (%esp) /* exit code is zero */
     call _exit /* exit application */
     hlt

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -26,7 +26,7 @@
  * ------------------------------------------------------------- *
  * | 104 | 112 | | *
  * ------------------------------------------------------------- *
- * |sbase|slimt| | *
+ * | sp | size| | *
  * ------------------------------------------------------------- *
  * ------------------------------------------------------------- *
  * | 15 | 16 | 17 | 18 | 19 | 20 | | *
@@ -112,6 +112,8 @@
     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 base
+ lw $t1, 112($a0) # load size of context stack
+ add $t0, $t1, $t0 # compute start address of context stack
 
     sub $sp, $sp, 28
     sw $ra, 24($sp)

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -33,7 +33,7 @@
  * ------------------------------------------------------------- *
  * | 92 | 96 | | *
  * ------------------------------------------------------------- *
- * |sbase|slimt| | *
+ * | sp | size| | *
  * ------------------------------------------------------------- *
  * ------------------------------------------------------------- *
  * | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | *
@@ -186,6 +186,8 @@
 make_fcontext:
     stw %r4, 88(%r3) # save address of context function
     lwz %r0, 92(%r3) # load address of context stack base
+ lwz %r4, 96(%r3) # load size of context stack
+ add %r0, %r4, %r0 # compute start address of context stack
 
     li %r4, 28
     subf %r1, %r4, %r1 # reserve space on stack

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -47,7 +47,7 @@
  * ------------------------------------------------------------- *
  * | 184 | 188 | 192 | 196 | | *
  * ------------------------------------------------------------- *
- * | sbase | slimt | | *
+ * | sp | size | | *
  * ------------------------------------------------------------- *
  * ------------------------------------------------------------- *
  * | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | *
@@ -214,6 +214,8 @@
 .make_fcontext:
     std %r4, 176(%r3) # save address of context function
     ld %r0, 184(%r3) # load address of context stack base
+ ld %r4, 192(%r3) # load size of context stack
+ add %r0, %r4, %r0 # compute start address of context stack
 
     li %r4, 56
     subf %r1, %r4, %r1 # reserve space on stack

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -30,7 +30,7 @@
 ; ----------------------------------------------------------------------------------
 ; | 0x50 | 0x54 | 0x58 | 0x5c | 0x60 | 0x64 | |
 ; ----------------------------------------------------------------------------------
-; | base | limit | size | |
+; | sp | size | base | |
 ; ----------------------------------------------------------------------------------
 ; ----------------------------------------------------------------------------------
 ; | 26 | 27 | |
@@ -101,9 +101,9 @@
 
     mov r10, gs:[030h] ; load NT_TIB
     mov rax, [r10+08h] ; load current stack base
- mov [rcx+050h], rax ; save current stack base
+ mov [rcx+060h], rax ; save current stack base
     mov rax, [r10+010h] ; load current stack limit
- mov [rcx+058h], rax ; save current stack limit
+ mov [rcx+050h], rax ; save current stack limit
     mov rax, [r10+018h] ; load fiber local storage
     mov [rcx+068h], rax ; save fiber local storage
 
@@ -112,7 +112,7 @@
 
     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
+ mov r10, [rcx+078h] ; address of aligned XMM storage
     movaps [r10], xmm6
     movaps [r10+010h], xmm7
     movaps [r10+020h], xmm8
@@ -126,7 +126,7 @@
 
     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
+ mov r10, [rdx+078h] ; address of aligned XMM storage
     movaps xmm6, [r10]
     movaps xmm7, [r10+010h]
     movaps xmm8, [r10+020h]
@@ -154,9 +154,9 @@
     mov rbp, [rdx+038h] ; restore RBP
 
     mov r10, gs:[030h] ; load NT_TIB
- mov rax, [rdx+050h] ; load stack base
+ mov rax, [rdx+060h] ; load stack base
     mov [r10+08h], rax ; restore stack base
- mov rax, [rdx+058h] ; load stack limit
+ mov rax, [rdx+050h] ; load stack limit
     mov [r10+010h], rax ; restore stack limit
     mov rax, [rdx+068h] ; load fiber local storage
     mov [r10+018h], rax ; restore fiber local storage
@@ -170,40 +170,44 @@
     jmp r10 ; indirect jump to caller
 jump_fcontext ENDP
 
-make_fcontext PROC EXPORT FRAME ; generate function table entry in .pdata and unwind information in E
+make_fcontext PROC EXPORT FRAME ; generate function table entry in .pdata and unwind information in
     .endprolog ; .xdata for a function's structured exception handling unwind behavior
 
+ push rbp ; save previous frame pointer; get the stack 16 byte aligned
+ mov rbp, rsp ; set RBP to RSP
+ sub rsp, 040h ; allocate shadow space
+
     mov [rcx+048h], rdx ; save address of context function
- mov rdx, [rcx+050h] ; load address of context stack base
- mov r8, [rcx+060h] ; load context stack size
- neg r8 ; negate r8 for LEA
- lea r8, [rdx+r8] ; compute the address of context stack limit
- mov [rcx+058h], r8 ; save the address of context stack limit
+ mov rdx, [rcx+050h] ; load address of context stack pointer (limit)
+ mov r8, [rcx+058h] ; load context stack size
+ lea rdx, [rdx+r8] ; compute top address of context stack (base)
+ mov [rcx+060h], rdx ; save top address of context stack (base)
 
- push rcx ; save pointer to fcontext_t
- sub rsp, 028h ; reserve shadow space for align_stack
+ mov [rbp-08h], rcx ; save pointer to fcontext_t
     mov rcx, rdx ; context stack pointer as arg for align_stack
- mov [rsp+8], rcx
     call align_stack ; call align_stack
     mov rdx, rax ; begin of aligned context stack
- add rsp, 028h
- pop rcx ; restore pointer to fcontext_t
-
- lea rdx, [rdx-028h] ; reserve 32byte shadow space + return address on stack, (RSP + 8) % 16 == 0
- mov [rcx+040h], rdx ; save the address where the context stack begins
+ mov rcx, [rbp-08h] ; restore pointer to fcontext_t
 
     stmxcsr [rcx+070h] ; save MMX control and status word
     fnstcw [rcx+074h] ; save x87 control word
 
- lea rax, finish ; helper code executed after fn() returns
- mov [rdx], rax ; store address off the helper function as return address
+ 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 rax, finish ; compute abs address of label finish
+ mov [rdx], rax ; 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 ; set RAX to zero
+ xor rax, rax
     ret
 
 finish:
- xor rcx, rcx
- mov [rsp+08h], rcx
+ ; RSP == stack pointer in fcontext + 0x8
+ xor rcx, rcx ; exit code is zero
     call _exit ; exit application
     hlt
 make_fcontext ENDP

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -26,7 +26,7 @@
  * ---------------------------------------------------------------------------------- *
  * | 0x40 | 0x44 | 0x48 | 0x4c | | *
  * ---------------------------------------------------------------------------------- *
- * | sbase | slimit | | *
+ * | sp | size | | *
  * ---------------------------------------------------------------------------------- *
  * ---------------------------------------------------------------------------------- *
  * | 20 | 21 | | *
@@ -86,30 +86,41 @@
 .type make_fcontext,@function
 .align 16
 make_fcontext:
- movq %rsi, 0x38(%rdi) /* save address of context function */
- movq 0x40(%rdi), %rdx /* load address of context stack base */
+ 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 */
+
+ movq %rsi, 0x38(%rdi) /* save address of context function */
+ movq 0x40(%rdi), %rdx /* load address of context stack base */
+ movq 0x48(%rdi), %rax /* load size of context stack */
+ leaq (%rdx,%rax), %rdx /* compute top address of context stack */
+
+ 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(%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 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 */
 
- pushq %rdi /* 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 */
- popq %rdi /* restore pointer to fcontext_t */
+ addq $0x10, %rsp /* deallocate shadow space */
+ popq %rbp /* restore previous frame pointer */
 
- leaq -0x8(%rdx), %rdx /* reserve space for the last frame on context stack, (RSP + 8) & 15 == 0 */
- movq %rdx, 0x30(%rdi) /* save the algined context stack base */
-
- stmxcsr 0x50(%rdi) /* save MMX control and status word */
- fnstcw 0x54(%rdi) /* save x87 control word */
-
- leaq finish(%rip), %rcx /* address of finish; called after context function returns */
- movq %rcx, (%rdx)
-
- xorq %rax, %rax
+ xorq %rax, %rax
     ret
 
 finish:
- xorq %rdi, %rdi /* exit code is zero */
- call _exit_at_PLT /* exit application */
+ /* RSP == stack pointer of context function + 0x8 */
+ xorq %rdi, %rdi /* exit code is zero */
+ call _exit_at_PLT /* exit application */
     hlt
 .size make_fcontext,.-make_fcontext
 

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-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -26,7 +26,7 @@
  * ---------------------------------------------------------------------------------- *
  * | 0x40 | 0x44 | 0x48 | 0x4c | | *
  * ---------------------------------------------------------------------------------- *
- * | sbase | slimit | | *
+ * | sp | size | | *
  * ---------------------------------------------------------------------------------- *
  * ---------------------------------------------------------------------------------- *
  * | 20 | 21 | | *
@@ -83,28 +83,39 @@
 .globl _make_fcontext
 .align 8
 _make_fcontext:
- movq %rsi, 0x38(%rdi) /* save address of context function */
- movq 0x40(%rdi), %rdx /* load address of context stack base */
+ 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 */
+
+ movq %rsi, 0x38(%rdi) /* save address of context function */
+ movq 0x40(%rdi), %rdx /* load address of context stack base */
+ movq 0x48(%rdi), %rax /* load size of context stack */
+ leaq (%rdx,%rax), %rdx /* compute top address of context stack */
+
+ 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(%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 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 */
 
- pushq %rdi /* 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 */
- popq %rdi /* restore pointer to fcontext_t */
+ addq $0x10, %rsp /* deallocate shadow space */
+ popq %rbp /* restore previous frame pointer */
 
- leaq -0x8(%rdx), %rdx /* reserve space for the last frame on context stack, (RSP + 8) % 16 == 0 */
- movq %rdx, 0x30(%rdi) /* save the algined context stack base */
-
- stmxcsr 0x50(%rdi) /* save MMX control and status word */
- fnstcw 0x54(%rdi) /* save x87 control word */
-
- leaq finish(%rip), %rcx /* helper code executed after context function returns */
- movq %rcx, (%rdx)
-
- xorq %rax, %rax /* set RAX to zero */
+ xorq %rax, %rax
     ret
 
 finish:
- xorq %rdi, %rdi /* exit code is zero */
- call _exit /* exit application */
+ /* RSP == stack pointer of context function + 0x8 */
+ xorq %rdi, %rdi /* exit code is zero */
+ call _exit /* exit application */
     hlt

Modified: trunk/libs/context/src/stack_allocator_posix.cpp
==============================================================================
--- trunk/libs/context/src/stack_allocator_posix.cpp (original)
+++ trunk/libs/context/src/stack_allocator_posix.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -44,8 +44,10 @@
             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 +1 for guard page
- std::size_t size_ = pages * pagesize();
+ const std::size_t pages( page_count( size) );
+ BOOST_ASSERT( 2 <= pages); // one page is reserved for protection
+ 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);
@@ -61,7 +63,7 @@
     const int result( ::mprotect( limit, pagesize(), PROT_NONE) );
     BOOST_ASSERT( 0 == result);
 
- return static_cast< char * >( limit) + size_;
+ return limit;
 }
 
 void
@@ -69,11 +71,10 @@
 {
     if ( vp)
     {
- const std::size_t pages( page_count( size) + 1); // add +1 for guard page
- std::size_t size_ = pages * pagesize();
+ const std::size_t pages = page_count( size);
+ const std::size_t size_ = pages * pagesize();
         BOOST_ASSERT( 0 < size && 0 < size_);
- void * limit = static_cast< char * >( vp) - size_;
- ::munmap( limit, size_);
+ ::munmap( vp, size_);
     }
 }
 

Modified: trunk/libs/context/src/stack_allocator_windows.cpp
==============================================================================
--- trunk/libs/context/src/stack_allocator_windows.cpp (original)
+++ trunk/libs/context/src/stack_allocator_windows.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -46,10 +46,11 @@
             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 +1 for guard page
- std::size_t size_ = pages * pagesize();
+ const std::size_t pages( page_count( size) );
+ BOOST_ASSERT( 2 <= pages); // one page is reserved for protection
+ const std::size_t size_ = pages * pagesize();
+ BOOST_ASSERT( 0 < size && 0 < size_);
 
-#ifndef BOOST_CONTEXT_FIBER
     void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
     if ( ! limit) throw std::bad_alloc();
 
@@ -58,8 +59,7 @@
         limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
     BOOST_ASSERT( FALSE != result);
 
- return static_cast< char * >( limit) + size_;
-#endif
+ return limit;
 }
 
 void
@@ -67,11 +67,10 @@
 {
     if ( vp)
     {
- const std::size_t pages( page_count( size) + 1); // add +1 for guard page
- std::size_t size_ = pages * pagesize();
+ const std::size_t pages = page_count( size);
+ 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);
+ ::VirtualFree( vp, 0, MEM_RELEASE);
     }
 }
 

Modified: trunk/libs/context/src/stack_utils_posix.cpp
==============================================================================
--- trunk/libs/context/src/stack_utils_posix.cpp (original)
+++ trunk/libs/context/src/stack_utils_posix.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -6,6 +6,8 @@
 
 #define BOOST_CONTEXT_SOURCE
 
+#include <algorithm>
+
 #include <boost/context/stack_utils.hpp>
 
 extern "C" {
@@ -39,21 +41,41 @@
     return limit;
 }
 
+static std::size_t compute_default_stacksize_()
+{
+ std::size_t size = 256 * 1024; // 256 kB
+ if ( boost::ctx::is_stack_unbound() )
+ return std::max( size, boost::ctx::minimum_stacksize() );
+
+ BOOST_ASSERT( boost::ctx::maximum_stacksize() >= boost::ctx::minimum_stacksize() );
+ return boost::ctx::maximum_stacksize() == boost::ctx::minimum_stacksize()
+ ? boost::ctx::minimum_stacksize()
+ : std::min( size, boost::ctx::maximum_stacksize() );
+}
+
 }
 
 namespace boost {
 namespace ctx {
 
 BOOST_CONTEXT_DECL
-std::size_t default_stacksize()
+std::size_t pagesize()
 {
- static std::size_t size = 256 * 1024;
+ static std::size_t size = ::getpagesize();
     return size;
 }
 
 BOOST_CONTEXT_DECL
-std::size_t minimum_stacksize()
-{ return SIGSTKSZ; }
+std::size_t page_count( std::size_t stacksize)
+{
+ return static_cast< std::size_t >(
+ std::ceil(
+ static_cast< float >( stacksize) / pagesize() ) );
+}
+
+BOOST_CONTEXT_DECL
+bool is_stack_unbound()
+{ return RLIM_INFINITY == stacksize_limit().rlim_max; }
 
 BOOST_CONTEXT_DECL
 std::size_t maximum_stacksize()
@@ -63,22 +85,18 @@
 }
 
 BOOST_CONTEXT_DECL
-bool is_stack_unbound()
-{ return RLIM_INFINITY == stacksize_limit().rlim_max; }
-
-BOOST_CONTEXT_DECL
-std::size_t pagesize()
+std::size_t minimum_stacksize()
 {
- static std::size_t pagesize( ::getpagesize() );
- return pagesize;
+ // space for guard page added
+ static std::size_t size = SIGSTKSZ + pagesize();
+ return size;
 }
 
 BOOST_CONTEXT_DECL
-std::size_t page_count( std::size_t stacksize)
+std::size_t default_stacksize()
 {
- return static_cast< std::size_t >(
- std::ceil(
- static_cast< float >( stacksize) / pagesize() ) );
+ static std::size_t size = compute_default_stacksize_();
+ return size;
 }
 
 }}

Modified: trunk/libs/context/src/stack_utils_windows.cpp
==============================================================================
--- trunk/libs/context/src/stack_utils_windows.cpp (original)
+++ trunk/libs/context/src/stack_utils_windows.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -5,6 +5,7 @@
 // http://www.boost.org/LICENSE_1_0.txt)
 
 #define BOOST_CONTEXT_SOURCE
+#define NOMINMAX
 
 #include <boost/context/stack_utils.hpp>
 
@@ -32,53 +33,67 @@
     return si;
 }
 
+static std::size_t compute_default_stacksize_()
+{
+ std::size_t size = 256 * 1024; // 256 kB
+ if ( boost::ctx::is_stack_unbound() )
+ return std::max( size, boost::ctx::minimum_stacksize() );
+
+ BOOST_ASSERT( boost::ctx::maximum_stacksize() >= boost::ctx::minimum_stacksize() );
+ return boost::ctx::maximum_stacksize() == boost::ctx::minimum_stacksize()
+ ? boost::ctx::minimum_stacksize()
+ : std::min( size, boost::ctx::maximum_stacksize() );
+}
+
 }
 
 namespace boost {
 namespace ctx {
 
 BOOST_CONTEXT_DECL
-std::size_t default_stacksize()
+std::size_t pagesize()
 {
- static std::size_t size = 256 * 1024;
+ static std::size_t size =
+ static_cast< std::size_t >( system_info().dwPageSize);
     return size;
 }
 
 BOOST_CONTEXT_DECL
-std::size_t minimum_stacksize()
+std::size_t page_count( std::size_t stacksize)
 {
- static std::size_t stacksize(
- static_cast< std::size_t >( system_info().dwAllocationGranularity) );
- return stacksize;
+ return static_cast< std::size_t >(
+ std::ceil(
+ static_cast< float >( stacksize) / pagesize() ) );
 }
 
+// Windows seams not to provide a limit for the stacksize
+BOOST_CONTEXT_DECL
+bool is_stack_unbound()
+{ return true; }
+
 BOOST_CONTEXT_DECL
 std::size_t maximum_stacksize()
 {
     BOOST_ASSERT( ! is_stack_unbound() );
- static std::size_t stacksize = 8 * 1024 * 1024;
- return stacksize;
+ static std::size_t size = 1 * 1024 * 1024 * 1024; // 1GB
+ return size;
 }
 
-// Windows seams not to provide a limit for the stacksize
-BOOST_CONTEXT_DECL
-bool is_stack_unbound()
-{ return true; }
-
 BOOST_CONTEXT_DECL
-std::size_t pagesize()
+std::size_t minimum_stacksize()
 {
- static std::size_t pagesize(
- static_cast< std::size_t >( system_info().dwPageSize) );
- return pagesize;
+ // space for guard page added
+ static std::size_t size =
+ static_cast< std::size_t >( system_info().dwAllocationGranularity)
+ + pagesize();
+ return size;
 }
 
 BOOST_CONTEXT_DECL
-std::size_t page_count( std::size_t stacksize)
+std::size_t default_stacksize()
 {
- return static_cast< std::size_t >(
- std::ceil(
- static_cast< float >( stacksize) / pagesize() ) );
+ static std::size_t size = compute_default_stacksize_();
+ return size;
 }
 
 }}

Modified: trunk/libs/context/test/test_context.cpp
==============================================================================
--- trunk/libs/context/test/test_context.cpp (original)
+++ trunk/libs/context/test/test_context.cpp 2012-08-31 15:50:07 EDT (Fri, 31 Aug 2012)
@@ -74,13 +74,20 @@
     ctx::jump_fcontext( & fc1, & fcm, 0);
 }
 
+void test_stack_utils()
+{
+ if ( ! ctx::is_stack_unbound() )
+ BOOST_CHECK( ctx::maximum_stacksize() >= ctx::default_stacksize() );
+ BOOST_CHECK( ctx::default_stacksize() >= ctx::minimum_stacksize() );
+}
+
 void test_start()
 {
     value1 = 0;
 
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.sp = alloc.allocate( ctx::minimum_stacksize() );
     fc1.fc_stack.size = ctx::minimum_stacksize();
     ctx::make_fcontext( & fc1, f1);
 
@@ -95,7 +102,7 @@
 
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.sp = alloc.allocate( ctx::minimum_stacksize() );
     fc1.fc_stack.size = ctx::minimum_stacksize();
     ctx::make_fcontext( & fc1, f3);
 
@@ -110,7 +117,7 @@
 {
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.sp = alloc.allocate( ctx::minimum_stacksize() );
     fc1.fc_stack.size = ctx::minimum_stacksize();
     ctx::make_fcontext( & fc1, f4);
 
@@ -122,7 +129,7 @@
 {
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.sp = alloc.allocate( ctx::minimum_stacksize() );
     fc1.fc_stack.size = ctx::minimum_stacksize();
     int i = 7;
     ctx::make_fcontext( & fc1, f5);
@@ -135,7 +142,7 @@
 {
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.sp = alloc.allocate( ctx::minimum_stacksize() );
     fc1.fc_stack.size = ctx::minimum_stacksize();
     std::pair< int, int > data = std::make_pair( 3, 7);
     ctx::make_fcontext( & fc1, f6);
@@ -151,7 +158,7 @@
 {
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.sp = alloc.allocate( ctx::minimum_stacksize() );
     fc1.fc_stack.size = ctx::minimum_stacksize();
     const char * what = "hello world";
     ctx::make_fcontext( & fc1, f7);
@@ -164,7 +171,7 @@
 {
     ctx::stack_allocator alloc;
 
- fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.sp = alloc.allocate( ctx::minimum_stacksize() );
     fc1.fc_stack.size = ctx::minimum_stacksize();
     double d = 7.13;
     ctx::make_fcontext( & fc1, f8);
@@ -178,6 +185,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_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