diff options
Diffstat (limited to 'libs/context')
75 files changed, 6687 insertions, 0 deletions
diff --git a/libs/context/build/Jamfile.v2 b/libs/context/build/Jamfile.v2 new file mode 100644 index 0000000000..bbe9e87255 --- /dev/null +++ b/libs/context/build/Jamfile.v2 @@ -0,0 +1,373 @@ + +# Boost.Context Library Build Jamfile + +# 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) + +import common ; +import feature ; +import indirect ; +import modules ; +import os ; +import toolset ; +import architecture ; + +project boost/context + : source-location ../src + : requirements + <os>SOLARIS:<define>_XOPEN_SOURCE=1 + <os>SOLARIS:<define>_XOPEN_SOURCE_EXTENDED=1 + : usage-requirements + <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 "$(<)" "$(>)" +} + +actions masm +{ + ml /c /Fo"$(<)" "$(>)" +} + +actions masm64 +{ + ml64 /c /Fo"$(<)" "$(>)" +} + + +rule configure ( properties * ) +{ + local result ; + + if ( ! ( <toolset>gcc in $(properties) + || <toolset>intel in $(properties) + || <toolset>msvc in $(properties) ) ) + { + result = <build>no ; + ECHO "toolset not supported" ; + } + + return $(result) ; +} + +# ARM +alias asm_context_sources + : asm/fcontext_arm_aapcs_elf_gas.S + : <abi>aapcs + <architecture>arm + <binary-format>elf + <toolset>gcc + ; + +alias asm_context_sources + : [ make asm/fcontext_arm_aapcs_elf_gas.o : asm/fcontext_arm_aapcs_elf_gas.S : @gas ] + : <abi>aapcs + <architecture>arm + <binary-format>elf + ; + +# MIPS 32bit +alias asm_context_sources + : asm/fcontext_mips32_o32_elf_gas.S + : <abi>o32 + <architecture>mips1 + <binary-format>elf + <toolset>gcc + ; + +alias asm_context_sources + : [ make asm/fcontext_mips32_o32_elf_gas.o : asm/fcontext_mips32_o32_elf_gas.S : @gas ] + : <abi>o32 + <architecture>mips1 + <binary-format>elf + ; + +# POWERPC 32bit +alias asm_context_sources + : asm/fcontext_ppc32_sysv_elf_gas.S + : <abi>sysv + <address-model>32 + <architecture>power + <binary-format>elf + <toolset>gcc + ; + +alias asm_context_sources + : [ make asm/fcontext_ppc32_sysv_elf_gas.o : asm/fcontext_ppc32_sysv_elf_gas.S : @gas ] + : <abi>sysv + <address-model>32 + <architecture>power + <binary-format>elf + ; + +# POWERPC 64bit +alias asm_context_sources + : asm/fcontext_ppc64_sysv_elf_gas.S + : <abi>sysv + <address-model>64 + <architecture>power + <binary-format>elf + <toolset>gcc + ; + +alias asm_context_sources + : [ make asm/fcontext_ppc64_sysv_elf_gas.o : asm/fcontext_ppc64_sysv_elf_gas.S : @gas ] + : <abi>sysv + <address-model>64 + <architecture>power + <binary-format>elf + ; + +# I386 +alias asm_context_sources + : asm/fcontext_i386_sysv_elf_gas.S + : <abi>sysv + <address-model>32 + <architecture>x86 + <binary-format>elf + <toolset>gcc + ; + +alias asm_context_sources + : asm/fcontext_i386_sysv_elf_gas.S + : <abi>sysv + <address-model>32 + <architecture>x86 + <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 ] + : <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 + : <abi>sysv + <address-model>32 + <architecture>x86 + <binary-format>mach-o + <target-os>darwin + <toolset>intel + ; + +alias asm_context_sources + : [ make asm/fcontext_i386_sysv_macho_gas.o : asm/fcontext_i386_sysv_macho_gas.S : @gas ] + : <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 + : <abi>ms + <address-model>32 + <architecture>x86 + <binary-format>pe + <target-os>windows + <toolset>intel + ; + +alias asm_context_sources + : asm/fcontext_i386_ms_pe_masm.asm + : <abi>ms + <address-model>32 + <architecture>x86 + <binary-format>pe + <target-os>windows + <toolset>msvc + ; + +alias asm_context_sources + : [ make asm/fcontext_i386_ms_pe_masm.o : asm/fcontext_i386_ms_pe_masm.asm : @masm ] + : <abi>ms + <address-model>32 + <architecture>x86 + <binary-format>pe + <target-os>windows + <toolset>gcc + ; + + +# X86_64 +alias asm_context_sources + : asm/fcontext_x86_64_sysv_elf_gas.S + : <abi>sysv + <address-model>64 + <architecture>x86 + <binary-format>elf + <toolset>gcc + ; + +alias asm_context_sources + : asm/fcontext_x86_64_sysv_elf_gas.S + : <abi>sysv + <address-model>64 + <architecture>x86 + <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 ] + : <abi>sysv + <address-model>64 + <architecture>x86 + <binary-format>elf + ; + + +alias asm_context_sources + : asm/fcontext_x86_64_sysv_macho_gas.S + : <abi>sysv + <address-model>64 + <architecture>x86 + <binary-format>mach-o + <target-os>darwin + <toolset>gcc + ; + +alias asm_context_sources + : asm/fcontext_x86_64_sysv_macho_gas.S + : <abi>sysv + <address-model>64 + <architecture>x86 + <binary-format>mach-o + <target-os>darwin + <toolset>intel + ; + +alias asm_context_sources + : [ make asm/fcontext_x86_64_sysv_macho_gas.o : asm/fcontext_x86_64_sysv_macho_gas.S : @gas ] + : <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 + : <abi>ms + <address-model>64 + <architecture>x86 + <binary-format>pe + <target-os>windows + <toolset>intel + ; + +alias asm_context_sources + : asm/fcontext_x86_64_ms_pe_masm.asm + : <abi>ms + <address-model>64 + <architecture>x86 + <binary-format>pe + <target-os>windows + <toolset>msvc + ; + +alias asm_context_sources + : [ make asm/fcontext_x86_64_ms_pe_masm.o : asm/fcontext_x86_64_ms_pe_masm.asm : @masm64 ] + : <abi>ms + <address-model>64 + <architecture>x86 + <binary-format>pe + <target-os>windows + <toolset>gcc + ; + +explicit asm_context_sources ; + + +alias select_asm_context_sources + : asm_context_sources + : [ architecture.architecture ] + [ architecture.address-model ] + ; + + +alias context_sources + : fcontext.cpp + seh.cpp + stack_allocator_windows.cpp + stack_utils_windows.cpp + : <target-os>windows + ; + +alias context_sources + : fcontext.cpp + stack_allocator_posix.cpp + stack_utils_posix.cpp + ; + +explicit context_sources ; + + +lib boost_context + : select_asm_context_sources + context_sources + : <link>shared:<define>BOOST_CONTEXT_DYN_LINK=1 + ; + + +boost-install boost_context ; diff --git a/libs/context/build/architecture.jam b/libs/context/build/architecture.jam new file mode 100644 index 0000000000..e06b1d2cda --- /dev/null +++ b/libs/context/build/architecture.jam @@ -0,0 +1,76 @@ +# architecture.jam +# +# Copyright 2012 Steven Watanabe +# +# 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) + +import configure ; +import project ; +import path ; +import property ; + +local here = [ modules.binding $(__name__) ] ; + +project.push-current [ project.current ] ; +project.load [ path.join [ path.make $(here:D) ] ../config ] ; +project.pop-current ; + +rule deduce-address-model ( properties * ) +{ + local result = [ property.select <address-model> : $(properties) ] ; + if $(result) + { + return $(result) ; + } + else + { + if [ configure.builds /boost/architecture//32 : $(properties) : 32-bit ] + { + return <address-model>32 ; + } + else if [ configure.builds /boost/architecture//64 : $(properties) : 64-bit ] + { + return <address-model>64 ; + } + } +} + +rule address-model ( ) +{ + return <conditional>@architecture.deduce-address-model ; +} + +rule deduce-architecture ( properties * ) +{ + local result = [ property.select <architecture> : $(properties) ] ; + if $(result) + { + return $(result) ; + } + else + { + if [ configure.builds /boost/architecture//x86 : $(properties) : x86 ] + { + return <architecture>x86 ; + } + else if [ configure.builds /boost/architecture//power : $(properties) : power ] + { + return <architecture>power ; + } + else if [ configure.builds /boost/architecture//arm : $(properties) : arm ] + { + return <architecture>arm ; + } + else if [ configure.builds /boost/architecture//mips1 : $(properties) : mips1 ] + { + return <architecture>mips1 ; + } + } +} + +rule architecture ( ) +{ + return <conditional>@architecture.deduce-architecture ; +} diff --git a/libs/context/config/32.cpp b/libs/context/config/32.cpp new file mode 100644 index 0000000000..d3d2dba29c --- /dev/null +++ b/libs/context/config/32.cpp @@ -0,0 +1,9 @@ +// 32.cpp +// +// Copyright (c) 2012 Steven Watanabe +// +// 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) + +int test[sizeof(void*) == 4? 1 : -1]; diff --git a/libs/context/config/64.cpp b/libs/context/config/64.cpp new file mode 100644 index 0000000000..5a33bc6452 --- /dev/null +++ b/libs/context/config/64.cpp @@ -0,0 +1,9 @@ +// 64.cpp +// +// Copyright (c) 2012 Steven Watanabe +// +// 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) + +int test[sizeof(void*) == 8? 1 : -1]; diff --git a/libs/context/config/Jamfile.jam b/libs/context/config/Jamfile.jam new file mode 100644 index 0000000000..a9a7b3f446 --- /dev/null +++ b/libs/context/config/Jamfile.jam @@ -0,0 +1,17 @@ +# Jamfile.jam +# +# Copyright 2012 Steven Watanabe +# +# 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) + +project /boost/architecture ; + +obj 32 : 32.cpp ; +obj 64 : 64.cpp ; + +obj power : power.cpp ; +obj x86 : x86.cpp ; +obj mips1 : mips1.cpp ; +obj arm : arm.cpp ; diff --git a/libs/context/config/arm.cpp b/libs/context/config/arm.cpp new file mode 100644 index 0000000000..e56cddf039 --- /dev/null +++ b/libs/context/config/arm.cpp @@ -0,0 +1,13 @@ +// arm.cpp +// +// Copyright (c) 2012 Steven Watanabe +// +// 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) + +#if !defined(__arm__) && !defined(__thumb__) && \ + !defined(__TARGET_ARCH_ARM) && !defined(__TARGET_ARCH_THUMB) && \ + !defined(_ARM) +#error "Not ARM" +#endif diff --git a/libs/context/config/mips1.cpp b/libs/context/config/mips1.cpp new file mode 100644 index 0000000000..adc4a61d03 --- /dev/null +++ b/libs/context/config/mips1.cpp @@ -0,0 +1,11 @@ +// mips1.cpp +// +// Copyright (c) 2012 Steven Watanabe +// +// 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) + +#if !((defined(__mips) && __mips == 1) || defined(_MIPS_ISA_MIPS1) || defined(_R3000)) +#error "Not MIPS1" +#endif diff --git a/libs/context/config/power.cpp b/libs/context/config/power.cpp new file mode 100644 index 0000000000..0551194a97 --- /dev/null +++ b/libs/context/config/power.cpp @@ -0,0 +1,14 @@ +// power.cpp +// +// Copyright (c) 2012 Steven Watanabe +// +// 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) + +#if !defined(__powerpc) && !defined(__powerpc__) && !defined(__ppc) \ + && !defined(__ppc__) && !defined(_M_PPC) && !defined(_ARCH_PPC) \ + && !defined(__POWERPC__) && !defined(__PPCGECKO__) \ + && !defined(__PPCBROADWAY) && !defined(_XENON) +#error "Not PPC" +#endif diff --git a/libs/context/config/x86.cpp b/libs/context/config/x86.cpp new file mode 100644 index 0000000000..0d2f9c2e90 --- /dev/null +++ b/libs/context/config/x86.cpp @@ -0,0 +1,16 @@ +// x86.cpp +// +// Copyright (c) 2012 Steven Watanabe +// +// 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) + +#if !defined(i386) && !defined(__i386__) && !defined(__i386) \ + && !defined(__i486__) && !defined(__i586__) && !defined(__i686__) \ + && !defined(_M_IX86) && !defined(__X86__) && !defined(_X86_) \ + && !defined(__THW_INTEL__) && !defined(__I86__) && !defined(__INTEL__) \ + && !defined(__amd64__) && !defined(__x86_64__) && !defined(__amd64) \ + && !defined(__x86_64) && !defined(_M_X64) +#error "Not x86" +#endif diff --git a/libs/context/doc/Jamfile.v2 b/libs/context/doc/Jamfile.v2 new file mode 100644 index 0000000000..df263bbd4b --- /dev/null +++ b/libs/context/doc/Jamfile.v2 @@ -0,0 +1,25 @@ +# (C) Copyright 2008 Anthony Williams +# +# 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) + +xml context : context.qbk ; + +boostbook standalone + : + context + : + # HTML options first: + # How far down we chunk nested sections, basically all of them: + <xsl:param>chunk.section.depth=3 + # Don't put the first section on the same page as the TOC: + <xsl:param>chunk.first.sections=1 + # How far down sections get TOC's + <xsl:param>toc.section.depth=10 + # Max depth in each TOC: + <xsl:param>toc.max.depth=3 + # How far down we go with TOC's + <xsl:param>generate.section.toc.level=10 + # Path for links to Boost: + <xsl:param>boost.root=../../../.. + ; diff --git a/libs/context/doc/acknowledgements.qbk b/libs/context/doc/acknowledgements.qbk new file mode 100644 index 0000000000..34f02308db --- /dev/null +++ b/libs/context/doc/acknowledgements.qbk @@ -0,0 +1,15 @@ +[/ + 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:acknowledgements Acknowledgments] + +I'd like to thank Adreas Fett, Artyom Beilis, Daniel Larimer, Fernando Pelliccioni, +Giovanni Piero Deretta, Gordon Woodhull, Helge Bahmann, Holger Grund, +Jeffrey Lee Hellrung (Jr.), Keith Jeffery, Phil Endecott, Robert Stewart, +Steven Watanabe, Vicente J. Botet Escriba, Wayne Piekarski. + +[endsect] diff --git a/libs/context/doc/config.qbk b/libs/context/doc/config.qbk new file mode 100644 index 0000000000..7716a4821c --- /dev/null +++ b/libs/context/doc/config.qbk @@ -0,0 +1,60 @@ +[/ + 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] diff --git a/libs/context/doc/context.qbk b/libs/context/doc/context.qbk new file mode 100644 index 0000000000..c12853bcbf --- /dev/null +++ b/libs/context/doc/context.qbk @@ -0,0 +1,75 @@ +[/ + 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 +] + +[article Context + [quickbook 1.4] + [authors [Kowalke, Oliver]] + [copyright 2009 Oliver Kowalke] + [purpose C++ Library for swiching different user ctx] + [category text] + [license + 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]) + ] +] + + +[def __boost_build__ [*Boost.Build]] +[def __boost_context__ [*Boost.Context]] +[def __boost_fiber__ [*Boost.Coroutine]] +[def __boost_task__ [*Boost.Task]] + +[template cs_example_link[link_text] [link context.examples.enumerator [link_text]]] +[template context_link[link_text] [link context.context.context [link_text]]] +[template stack_link[link_text] [link context.stack [link_text]]] +[template preformance_link[link_text] [link context.performance [link_text]]] + +[def __context_fn__ ['context-function]] +[def __coroutine__ ['coroutine]] +[def __coroutines__ ['coroutines]] +[def __coop_threads__ ['cooperative threads (userland threads)]] +[def __fls__ ['fiber-local storage]] +[def __guard_page__ ['guard-page]] +[def __not_a_context__ ['not-a-context]] +[def __stack__ [stack_link ['stack]]] +[def __thread__ ['thread]] +[def __threads__ ['threads]] +[def __tls__ ['thread-local storage]] +[def __stack_allocator__ ['StackAllocator]] +[def __stack_allocator_concept__ ['StackAllocator concept]] + +[def __fcontext__ ['fcontext_t]] +[def __ucontext__ ['ucontext_t]] + +[def __fls_alloc__ ['::FlsAlloc()]] +[def __fls_free__ ['::FlsFree()]] + +[def __bad_alloc__ ['std::bad_alloc]] +[def __fc_base__ ['fc_base]] +[def __fc_limit__ ['fc_limit]] +[def __fc_link__ ['fc_link]] +[def __jump_fcontext__ ['jump_fcontext()]] +[def __make_fcontext__ ['make_fcontext()]] +[def __invalid_argument__ ['std::invalid_argument]] +[def __stack_alloc__ ['allocate()]] +[def __stack_dealloc__ ['deallocate()]] +[def __stack_helper__ ['stack_helper]] +[def __yield__ ['yield]] + +[def __context_ns__ ['boost::ctx]] + +[include overview.qbk] +[include requirements.qbk] +[include fcontext.qbk] +[include stack.qbk] +[include performance.qbk] +[include tested.qbk] +[include rationale.qbk] +[include reference.qbk] +[include todo.qbk] +[include acknowledgements.qbk] diff --git a/libs/context/doc/fcontext.qbk b/libs/context/doc/fcontext.qbk new file mode 100644 index 0000000000..2c320f0cd7 --- /dev/null +++ b/libs/context/doc/fcontext.qbk @@ -0,0 +1,251 @@ +[/ + 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:context Context] + +Each instance of __fcontext__ represents a context (CPU registers and stack +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]. +__fcontext__ and its functions are located in __context_ns__ and the functions +are declared as extern "C". + +[warning If __fcontext__ is used in a multithreaded application, it can migrated +between threads, but must not reference __tls__.] + +[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__. + + // context-function + void f( intptr); + + // creates and manages a protected stack (with guard page) + ctx::stack_allocator alloc; + fc.fc_stack.base = alloc.allocate(ctx::minimum_stacksize()); + fc.fc_stack.limit = + static_cast< char * >( fc.fc_stack.base) - ctx::minimum_stacksize(); + + // 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 a pointer to the lower bound of the stack (__fc_limit__). + +Calling __jump_fcontext__ invokes the __context_fn__ in a newly created context +complete with registers, flags, stack and instruction pointers. When control +should be returned to the original calling context, call __jump_fcontext__. +The current context information (registers, flags, and stack and instruction +pointers) is saved and the original context information is restored. Calling +__jump_fcontext__ again resumes execution in the second context after saving the +new state of the original context. + + namespace ctx = boost::ctx; + + 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: return" << std::endl; + 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); + BOOST_ASSERT( false && ! "f2: never returns"); + } + + int main( int argc, char * argv[]) + { + ctx::stack_allocator alloc1, alloc2; + + fc1.fc_stack.base = alloc1.allocate(ctx::minimum_stacksize()); + fc1.fc_stack.limit = + static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc1, f1); + + fc2.fc_stack.base = alloc2.allocate(ctx::minimum_stacksize()); + fc2.fc_stack.limit = + static_cast< char * >( fc2.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc2, f2); + + std::cout << "main: call jump_fcontext( & fcm, & fc1, 0)" << std::endl; + ctx::jump_fcontext( & fcm, & fc1, 0); + + std::cout << "main: done" << std::endl; + + return EXIT_SUCCESS; + } + + output: + main: call jump_fcontext( & fcm, & fc1, 0) + f1: entered + f1: call jump_fcontext( & fc1, & fc2, 0) + f2: entered + f2: call jump_fcontext( & fc2, & fc1, 0) + f1: return + main: done + +First call of __jump_fcontext__ enters the __context_fn__ `f1()` by starting +context fc1 (context fcm saves the registers of `main()`). For jumping between +context's fc1 and fc2 `jump_fcontext()` is called. +Because context fcm is chained to fc1, `main()` is entered (returning from +__jump_fcontext__) after context fc1 becomes complete (return from `f1()`). + +[warning Calling __jump_fcontext__ to the same context from inside the same +context results in undefined behaviour.] + +[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.] + + +[heading Transfer of data] + +The third argument passed to __jump_fcontext__, in one context, is passed as +the first argument of the __context_fn__ if the context is started for the +first time. +In all following invocations of __jump_fcontext__ the intptr_t passed to +__jump_fcontext__, in one context, is returned by __jump_fcontext__ in the +other context. + + namespace ctx = boost::ctx; + + ctx::fcontext_t fc1, fcm; + + typedef std::pair< int, int > pair_t; + + void f1( intptr_t param) + { + pair_t * p = ( pair_t *) param; + + 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) ); + } + + int main( int argc, char * argv[]) + { + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize()); + fc1.fc_stack.limit = + static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + fc1.fc_link = & fcm; + pair_t p( std::make_pair( 2, 7) ); + ctx::make_fcontext( & fc1, f1); + + 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); + std::cout << p.first << " + " << p.second << " == " << res << std::endl; + + std::cout << "main: done" << std::endl; + + return EXIT_SUCCESS; + } + + output: + 2 + 7 == 9 + 5 + 6 == 11 + main: done + + +[heading Exceptions in __context_fn__] + +If the __context_fn__ emits an exception, the application will terminate. + + +[heading Preserving floating point registers] + +Preserving the floating point registers increases the cycle count for a context +switch (see performance tests). +The foruth argument of __jump_fcontext__ controls if fpu registers should be +preserved by the context jump. + +[important The use of the fpu controling argument of __jump_fcontext__ must +be consistent in the application. Otherwise the behaviour is undefined.] + + +[heading Stack unwinding] + +Sometimes it is necessary to unwind the stack of an unfinished context to +destroy local stack variables so they can release allocated resources (RAII +pattern). The user is responsible for this task. + + +[section:boost_fcontext Struct `fcontext_t` and related functions] + + struct stack_t + { + void * base; + void * limit; + }; + + struct fcontext_t + { + < platform specific > + + 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) ); + +[heading `base`] +[variablelist +[[Member:] [Pointer to the top of the stack.]] +] + +[heading `limit`] +[variablelist +[[Member:] [Pointer to the bottom of the stack.]] +] + +[heading `fc_stack`] +[variablelist +[[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)`] +[variablelist +[[Effects:] [Stores the current context data (stack pointer, instruction +pointer, and CPU registers) to `*ofc` and restores the context data from `*nfc`, +which implies jumping to `*nfc`'s execution context. The intptr_t argument, `p`, +is passed to the current context to be returned by the most recent call to +`jump_fcontext()` in the same thread. The last argument controls if fpu registers +have to be preserved.]] +[[Returns:] [The third pointer argument passed to the most recent call to +`jump_fcontext()`, if any.]] +] + +[heading `void make_fcontext( fcontext_t * fc, 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.]] +] + +[endsect] + +[endsect] diff --git a/libs/context/doc/html/context/acknowledgements.html b/libs/context/doc/html/context/acknowledgements.html new file mode 100644 index 0000000000..ac56768845 --- /dev/null +++ b/libs/context/doc/html/context/acknowledgements.html @@ -0,0 +1,48 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Acknowledgments</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="todo.html" title="Todo"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="todo.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.acknowledgements"></a><a class="link" href="acknowledgements.html" title="Acknowledgments">Acknowledgments</a> +</h2></div></div></div> +<p> + I'd like to thank Adreas Fett, Artyom Beilis, Daniel Larimer, Fernando Pelliccioni, + Giovanni Piero Deretta, Gordon Woodhull, Helge Bahmann, Holger Grund, Jeffrey + Lee Hellrung (Jr.), Keith Jeffery, Phil Endecott, Robert Stewart, Steven Watanabe, + Vicente J. Botet Escriba, Wayne Piekarski. + </p> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="todo.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/context.html b/libs/context/doc/html/context/context.html new file mode 100644 index 0000000000..ae9591ea73 --- /dev/null +++ b/libs/context/doc/html/context/context.html @@ -0,0 +1,294 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Context</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="requirements.html" title="Requirements"> +<link rel="next" href="context/boost_fcontext.html" title="Struct fcontext_t and related functions"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="requirements.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="context/boost_fcontext.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.context"></a><a class="link" href="context.html" title="Context">Context</a> +</h2></div></div></div> +<div class="toc"><dl><dt><span class="section"><a href="context/boost_fcontext.html">Struct <code class="computeroutput"><span class="identifier">fcontext_t</span></code> and related functions</a></span></dt></dl></div> +<p> + Each instance of <span class="emphasis"><em>fcontext_t</em></span> represents a context (CPU + registers and stack space). Together with its related functions <span class="emphasis"><em>jump_fcontext()</em></span> + and <span class="emphasis"><em>make_fcontext()</em></span> it provides a execution control transfer + mechanism similar interface like <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html" target="_top">ucontext_t</a>. + <span class="emphasis"><em>fcontext_t</em></span> and its functions are located in <span class="emphasis"><em>boost::ctx</em></span> + and the functions are declared as extern "C". + </p> +<div class="warning"><table border="0" summary="Warning"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../doc/src/images/warning.png"></td> +<th align="left">Warning</th> +</tr> +<tr><td align="left" valign="top"><p> + If <span class="emphasis"><em>fcontext_t</em></span> is used in a multithreaded application, + it can migrated between threads, but must not reference <span class="emphasis"><em>thread-local + storage</em></span>. + </p></td></tr> +</table></div> +<div class="note"><table border="0" summary="Note"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> +<th align="left">Note</th> +</tr> +<tr><td align="left" valign="top"><p> + If <span class="emphasis"><em>fiber-local storage</em></span> is used on Windows, the user + is responsible for calling <span class="emphasis"><em>::FlsAlloc()</em></span>, <span class="emphasis"><em>::FlsFree()</em></span>. + </p></td></tr> +</table></div> +<div class="important"><table border="0" summary="Important"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> +<th align="left">Important</th> +</tr> +<tr><td align="left" valign="top"><p> + The low level API is the part to port to new platforms. + </p></td></tr> +</table></div> +<h4> +<a name="context.context.h0"></a> + <span><a name="context.context.executing_a_context"></a></span><a class="link" href="context.html#context.context.executing_a_context">Executing + a context</a> + </h4> +<p> + A new context supposed to execute a <span class="emphasis"><em>context-function</em></span> (returning + void and accepting intptr_t as argument) must be initialized by function <span class="emphasis"><em>make_fcontext()</em></span>. + </p> +<pre class="programlisting"><span class="comment">// context-function</span> +<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span> <span class="identifier">intptr</span><span class="special">);</span> + +<span class="comment">// creates and manages a protected stack (with guard page)</span> +<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">stack_allocator</span> <span class="identifier">alloc</span><span class="special">;</span> +<span class="identifier">fc</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span> <span class="special">=</span> <span class="identifier">alloc</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">());</span> +<span class="identifier">fc</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">limit</span> <span class="special">=</span> + <span class="keyword">static_cast</span><span class="special"><</span> <span class="keyword">char</span> <span class="special">*</span> <span class="special">>(</span> <span class="identifier">fc</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">();</span> + +<span class="comment">// context fc uses f() as context function</span> +<span class="identifier">make_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> +</pre> +<p> + <span class="emphasis"><em>fcontext_t</em></span> requires a pointer to the top of the stack + (<span class="emphasis"><em>fc_base</em></span>) as well as a pointer to the lower bound of the + stack (<span class="emphasis"><em>fc_limit</em></span>). + </p> +<p> + Calling <span class="emphasis"><em>jump_fcontext()</em></span> invokes the <span class="emphasis"><em>context-function</em></span> + in a newly created context complete with registers, flags, stack and instruction + pointers. When control should be returned to the original calling context, + call <span class="emphasis"><em>jump_fcontext()</em></span>. The current context information + (registers, flags, and stack and instruction pointers) is saved and the original + context information is restored. Calling <span class="emphasis"><em>jump_fcontext()</em></span> + again resumes execution in the second context after saving the new state of + the original context. + </p> +<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ctx</span><span class="special">;</span> + +<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">fcontext_t</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="identifier">fc2</span><span class="special">;</span> + +<span class="keyword">void</span> <span class="identifier">f1</span><span class="special">(</span> <span class="identifier">intptr_t</span><span class="special">)</span> +<span class="special">{</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: entered"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: call jump_fcontext( & fc1, & fc2, 0)"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc2</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: return"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> +<span class="special">}</span> + +<span class="keyword">void</span> <span class="identifier">f2</span><span class="special">(</span> <span class="identifier">intptr_t</span><span class="special">)</span> +<span class="special">{</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f2: entered"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f2: call jump_fcontext( & fc2, & fc1, 0)"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc2</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> + <span class="identifier">BOOST_ASSERT</span><span class="special">(</span> <span class="keyword">false</span> <span class="special">&&</span> <span class="special">!</span> <span class="string">"f2: never returns"</span><span class="special">);</span> +<span class="special">}</span> + +<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">*</span> <span class="identifier">argv</span><span class="special">[])</span> +<span class="special">{</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">stack_allocator</span> <span class="identifier">alloc1</span><span class="special">,</span> <span class="identifier">alloc2</span><span class="special">;</span> + + <span class="identifier">fc1</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span> <span class="special">=</span> <span class="identifier">alloc1</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">());</span> + <span class="identifier">fc1</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">limit</span> <span class="special">=</span> + <span class="keyword">static_cast</span><span class="special"><</span> <span class="keyword">char</span> <span class="special">*</span> <span class="special">>(</span> <span class="identifier">fc1</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">();</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">make_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="identifier">f1</span><span class="special">);</span> + + <span class="identifier">fc2</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span> <span class="special">=</span> <span class="identifier">alloc2</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">());</span> + <span class="identifier">fc2</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">limit</span> <span class="special">=</span> + <span class="keyword">static_cast</span><span class="special"><</span> <span class="keyword">char</span> <span class="special">*</span> <span class="special">>(</span> <span class="identifier">fc2</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">();</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">make_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc2</span><span class="special">,</span> <span class="identifier">f2</span><span class="special">);</span> + + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"main: call jump_fcontext( & fcm, & fc1, 0)"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> + + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"main: done"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + + <span class="keyword">return</span> <span class="identifier">EXIT_SUCCESS</span><span class="special">;</span> +<span class="special">}</span> + +<span class="identifier">output</span><span class="special">:</span> + <span class="identifier">main</span><span class="special">:</span> <span class="identifier">call</span> <span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="number">0</span><span class="special">)</span> + <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">entered</span> + <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">call</span> <span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc2</span><span class="special">,</span> <span class="number">0</span><span class="special">)</span> + <span class="identifier">f2</span><span class="special">:</span> <span class="identifier">entered</span> + <span class="identifier">f2</span><span class="special">:</span> <span class="identifier">call</span> <span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc2</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="number">0</span><span class="special">)</span> + <span class="identifier">f1</span><span class="special">:</span> <span class="keyword">return</span> + <span class="identifier">main</span><span class="special">:</span> <span class="identifier">done</span> +</pre> +<p> + First call of <span class="emphasis"><em>jump_fcontext()</em></span> enters the <span class="emphasis"><em>context-function</em></span> + <code class="computeroutput"><span class="identifier">f1</span><span class="special">()</span></code> + by starting context fc1 (context fcm saves the registers of <code class="computeroutput"><span class="identifier">main</span><span class="special">()</span></code>). For jumping between context's fc1 and fc2 + <code class="computeroutput"><span class="identifier">jump_fcontext</span><span class="special">()</span></code> + is called. Because context fcm is chained to fc1, <code class="computeroutput"><span class="identifier">main</span><span class="special">()</span></code> is entered (returning from <span class="emphasis"><em>jump_fcontext()</em></span>) + after context fc1 becomes complete (return from <code class="computeroutput"><span class="identifier">f1</span><span class="special">()</span></code>). + </p> +<div class="warning"><table border="0" summary="Warning"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../doc/src/images/warning.png"></td> +<th align="left">Warning</th> +</tr> +<tr><td align="left" valign="top"><p> + Calling <span class="emphasis"><em>jump_fcontext()</em></span> to the same context from inside + the same context results in undefined behaviour. + </p></td></tr> +</table></div> +<div class="note"><table border="0" summary="Note"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> +<th align="left">Note</th> +</tr> +<tr><td align="left" valign="top"><p> + In contrast to threads, which are preemtive, <span class="emphasis"><em>fcontext_t</em></span> + switches are cooperative (programmer controls when switch will happen). The + kernel is not involved in the context switches. + </p></td></tr> +</table></div> +<h4> +<a name="context.context.h1"></a> + <span><a name="context.context.transfer_of_data"></a></span><a class="link" href="context.html#context.context.transfer_of_data">Transfer + of data</a> + </h4> +<p> + The third argument passed to <span class="emphasis"><em>jump_fcontext()</em></span>, in one context, + is passed as the first argument of the <span class="emphasis"><em>context-function</em></span> + if the context is started for the first time. In all following invocations + of <span class="emphasis"><em>jump_fcontext()</em></span> the intptr_t passed to <span class="emphasis"><em>jump_fcontext()</em></span>, + in one context, is returned by <span class="emphasis"><em>jump_fcontext()</em></span> in the + other context. + </p> +<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ctx</span><span class="special">;</span> + +<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">fcontext_t</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="identifier">fcm</span><span class="special">;</span> + +<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span> <span class="special">></span> <span class="identifier">pair_t</span><span class="special">;</span> + +<span class="keyword">void</span> <span class="identifier">f1</span><span class="special">(</span> <span class="identifier">intptr_t</span> <span class="identifier">param</span><span class="special">)</span> +<span class="special">{</span> + <span class="identifier">pair_t</span> <span class="special">*</span> <span class="identifier">p</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">pair_t</span> <span class="special">*)</span> <span class="identifier">param</span><span class="special">;</span> + + <span class="identifier">p</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">pair_t</span> <span class="special">*)</span> <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="special">(</span> <span class="identifier">intptr_t</span><span class="special">)</span> <span class="special">(</span> <span class="identifier">p</span><span class="special">-></span><span class="identifier">first</span> <span class="special">+</span> <span class="identifier">p</span><span class="special">-></span><span class="identifier">second</span><span class="special">)</span> <span class="special">);</span> + + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="special">(</span> <span class="identifier">intptr_t</span><span class="special">)</span> <span class="special">(</span> <span class="identifier">p</span><span class="special">-></span><span class="identifier">first</span> <span class="special">+</span> <span class="identifier">p</span><span class="special">-></span><span class="identifier">second</span><span class="special">)</span> <span class="special">);</span> +<span class="special">}</span> + +<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">*</span> <span class="identifier">argv</span><span class="special">[])</span> +<span class="special">{</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">stack_allocator</span> <span class="identifier">alloc</span><span class="special">;</span> + + <span class="identifier">fc1</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span> <span class="special">=</span> <span class="identifier">alloc</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">());</span> + <span class="identifier">fc1</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">limit</span> <span class="special">=</span> + <span class="keyword">static_cast</span><span class="special"><</span> <span class="keyword">char</span> <span class="special">*</span> <span class="special">>(</span> <span class="identifier">fc1</span><span class="special">.</span><span class="identifier">fc_stack</span><span class="special">.</span><span class="identifier">base</span><span class="special">)</span> <span class="special">-</span> <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">minimum_stacksize</span><span class="special">();</span> + <span class="identifier">fc1</span><span class="special">.</span><span class="identifier">fc_link</span> <span class="special">=</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">;</span> + <span class="identifier">pair_t</span> <span class="identifier">p</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">7</span><span class="special">)</span> <span class="special">);</span> + <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">make_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="identifier">f1</span><span class="special">);</span> + + <span class="keyword">int</span> <span class="identifier">res</span> <span class="special">=</span> <span class="special">(</span> <span class="keyword">int</span><span class="special">)</span> <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="special">(</span> <span class="identifier">intptr_t</span><span class="special">)</span> <span class="special">&</span> <span class="identifier">p</span><span class="special">);</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">first</span> <span class="special"><<</span> <span class="string">" + "</span> <span class="special"><<</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">second</span> <span class="special"><<</span> <span class="string">" == "</span> <span class="special"><<</span> <span class="identifier">res</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + + <span class="identifier">p</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span> <span class="number">5</span><span class="special">,</span> <span class="number">6</span><span class="special">);</span> + <span class="identifier">res</span> <span class="special">=</span> <span class="special">(</span> <span class="keyword">int</span><span class="special">)</span> <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="special">&</span> <span class="identifier">fcm</span><span class="special">,</span> <span class="special">&</span> <span class="identifier">fc1</span><span class="special">,</span> <span class="special">(</span> <span class="identifier">intptr_t</span><span class="special">)</span> <span class="special">&</span> <span class="identifier">p</span><span class="special">);</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">first</span> <span class="special"><<</span> <span class="string">" + "</span> <span class="special"><<</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">second</span> <span class="special"><<</span> <span class="string">" == "</span> <span class="special"><<</span> <span class="identifier">res</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + + <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"main: done"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> + + <span class="keyword">return</span> <span class="identifier">EXIT_SUCCESS</span><span class="special">;</span> +<span class="special">}</span> + +<span class="identifier">output</span><span class="special">:</span> + <span class="number">2</span> <span class="special">+</span> <span class="number">7</span> <span class="special">==</span> <span class="number">9</span> + <span class="number">5</span> <span class="special">+</span> <span class="number">6</span> <span class="special">==</span> <span class="number">11</span> + <span class="identifier">main</span><span class="special">:</span> <span class="identifier">done</span> +</pre> +<h4> +<a name="context.context.h2"></a> + <span><a name="context.context.exceptions_in__emphasis_context_function__emphasis_"></a></span><a class="link" href="context.html#context.context.exceptions_in__emphasis_context_function__emphasis_">Exceptions + in <span class="emphasis"><em>context-function</em></span></a> + </h4> +<p> + If the <span class="emphasis"><em>context-function</em></span> emits an exception, the application + will terminate. + </p> +<h4> +<a name="context.context.h3"></a> + <span><a name="context.context.preserving_floating_point_registers"></a></span><a class="link" href="context.html#context.context.preserving_floating_point_registers">Preserving + floating point registers</a> + </h4> +<p> + Preserving the floating point registers increases the cycle count for a context + switch (see performance tests). The foruth argument of <span class="emphasis"><em>jump_fcontext()</em></span> + controls if fpu registers should be preserved by the context jump. + </p> +<div class="important"><table border="0" summary="Important"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> +<th align="left">Important</th> +</tr> +<tr><td align="left" valign="top"><p> + The use of the fpu controling argument of <span class="emphasis"><em>jump_fcontext()</em></span> + must be consistent in the application. Otherwise the behaviour is undefined. + </p></td></tr> +</table></div> +<h4> +<a name="context.context.h4"></a> + <span><a name="context.context.stack_unwinding"></a></span><a class="link" href="context.html#context.context.stack_unwinding">Stack + unwinding</a> + </h4> +<p> + Sometimes it is necessary to unwind the stack of an unfinished context to destroy + local stack variables so they can release allocated resources (RAII pattern). + The user is responsible for this task. + </p> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="requirements.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="context/boost_fcontext.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/context/boost_fcontext.html b/libs/context/doc/html/context/context/boost_fcontext.html new file mode 100644 index 0000000000..fad862482b --- /dev/null +++ b/libs/context/doc/html/context/context/boost_fcontext.html @@ -0,0 +1,146 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Struct fcontext_t and related functions</title> +<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../../index.html" title="Context"> +<link rel="up" href="../context.html" title="Context"> +<link rel="prev" href="../context.html" title="Context"> +<link rel="next" href="../stack.html" title="Stack allocation"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> +<td align="center"><a href="../../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../context.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../context.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../stack.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h3 class="title"> +<a name="context.context.boost_fcontext"></a><a class="link" href="boost_fcontext.html" title="Struct fcontext_t and related functions">Struct <code class="computeroutput"><span class="identifier">fcontext_t</span></code> and related functions</a> +</h3></div></div></div> +<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">stack_t</span> +<span class="special">{</span> + <span class="keyword">void</span> <span class="special">*</span> <span class="identifier">base</span><span class="special">;</span> + <span class="keyword">void</span> <span class="special">*</span> <span class="identifier">limit</span><span class="special">;</span> +<span class="special">};</span> + +<span class="keyword">struct</span> <span class="identifier">fcontext_t</span> +<span class="special">{</span> + <span class="special"><</span> <span class="identifier">platform</span> <span class="identifier">specific</span> <span class="special">></span> + + <span class="identifier">stack_t</span> <span class="identifier">fc_stack</span><span class="special">;</span> +<span class="special">};</span> + +<span class="identifier">intptr_t</span> <span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="identifier">fcontext_t</span> <span class="special">*</span> <span class="identifier">ofc</span><span class="special">,</span> <span class="identifier">fcontext_t</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">nfc</span><span class="special">,</span> <span class="identifier">intptr_t</span> <span class="identifier">vp</span><span class="special">);</span> +<span class="keyword">void</span> <span class="identifier">make_fcontext</span><span class="special">(</span> <span class="identifier">fcontext_t</span> <span class="special">*</span> <span class="identifier">fc</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(*</span> <span class="identifier">fn</span><span class="special">)(</span><span class="identifier">intptr_t</span><span class="special">)</span> <span class="special">);</span> +</pre> +<h5> +<a name="context.context.boost_fcontext.h0"></a> + <span><a name="context.context.boost_fcontext._code__phrase_role__identifier__base__phrase___code_"></a></span><a class="link" href="boost_fcontext.html#context.context.boost_fcontext._code__phrase_role__identifier__base__phrase___code_"><code class="computeroutput"><span class="identifier">base</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Member:</span></dt> +<dd><p> + Pointer to the top of the stack. + </p></dd> +</dl> +</div> +<h5> +<a name="context.context.boost_fcontext.h1"></a> + <span><a name="context.context.boost_fcontext._code__phrase_role__identifier__limit__phrase___code_"></a></span><a class="link" href="boost_fcontext.html#context.context.boost_fcontext._code__phrase_role__identifier__limit__phrase___code_"><code class="computeroutput"><span class="identifier">limit</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Member:</span></dt> +<dd><p> + Pointer to the bottom of the stack. + </p></dd> +</dl> +</div> +<h5> +<a name="context.context.boost_fcontext.h2"></a> + <span><a name="context.context.boost_fcontext._code__phrase_role__identifier__fc_stack__phrase___code_"></a></span><a class="link" href="boost_fcontext.html#context.context.boost_fcontext._code__phrase_role__identifier__fc_stack__phrase___code_"><code class="computeroutput"><span class="identifier">fc_stack</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Member:</span></dt> +<dd><p> + Tracks the memory for the context's stack. + </p></dd> +</dl> +</div> +<h5> +<a name="context.context.boost_fcontext.h3"></a> + <span><a name="context.context.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__jump_fcontext__phrase__phrase_role__special_____phrase___phrase_role__identifier__fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase___phrase_role__identifier__fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___phrase_role__keyword__bool__phrase___phrase_role__identifier__preserve_fpu__phrase__phrase_role__special_____phrase___code_"></a></span><a class="link" href="boost_fcontext.html#context.context.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__jump_fcontext__phrase__phrase_role__special_____phrase___phrase_role__identifier__fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase___phrase_role__identifier__fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___phrase_role__keyword__bool__phrase___phrase_role__identifier__preserve_fpu__phrase__phrase_role__special_____phrase___code_"><code class="computeroutput"><span class="identifier">intptr_t</span> <span class="identifier">jump_fcontext</span><span class="special">(</span> <span class="identifier">fcontext_t</span> + <span class="special">*</span> <span class="identifier">ofc</span><span class="special">,</span> <span class="identifier">fcontext_t</span> + <span class="special">*</span> <span class="identifier">nfc</span><span class="special">,</span> <span class="identifier">intptr_t</span> <span class="identifier">p</span><span class="special">,</span> <span class="keyword">bool</span> + <span class="identifier">preserve_fpu</span><span class="special">)</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Effects:</span></dt> +<dd><p> + Stores the current context data (stack pointer, instruction pointer, + and CPU registers) to <code class="computeroutput"><span class="special">*</span><span class="identifier">ofc</span></code> and restores the context data + from <code class="computeroutput"><span class="special">*</span><span class="identifier">nfc</span></code>, + which implies jumping to <code class="computeroutput"><span class="special">*</span><span class="identifier">nfc</span></code>'s execution context. The intptr_t + argument, <code class="computeroutput"><span class="identifier">p</span></code>, is passed + to the current context to be returned by the most recent call to <code class="computeroutput"><span class="identifier">jump_fcontext</span><span class="special">()</span></code> + in the same thread. The last argument controls if fpu registers have + to be preserved. + </p></dd> +<dt><span class="term">Returns:</span></dt> +<dd><p> + The third pointer argument passed to the most recent call to <code class="computeroutput"><span class="identifier">jump_fcontext</span><span class="special">()</span></code>, + if any. + </p></dd> +</dl> +</div> +<h5> +<a name="context.context.boost_fcontext.h4"></a> + <span><a name="context.context.boost_fcontext._code__phrase_role__keyword__void__phrase___phrase_role__identifier__make_fcontext__phrase__phrase_role__special_____phrase___phrase_role__identifier__fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__fc__phrase__phrase_role__special_____phrase___phrase_role__keyword__void__phrase__phrase_role__special______phrase__phrase_role__identifier__fn__phrase__phrase_role__special______phrase__phrase_role__identifier__intptr_t__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="boost_fcontext.html#context.context.boost_fcontext._code__phrase_role__keyword__void__phrase___phrase_role__identifier__make_fcontext__phrase__phrase_role__special_____phrase___phrase_role__identifier__fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__fc__phrase__phrase_role__special_____phrase___phrase_role__keyword__void__phrase__phrase_role__special______phrase__phrase_role__identifier__fn__phrase__phrase_role__special______phrase__phrase_role__identifier__intptr_t__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="keyword">void</span> <span class="identifier">make_fcontext</span><span class="special">(</span> <span class="identifier">fcontext_t</span> + <span class="special">*</span> <span class="identifier">fc</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(*</span><span class="identifier">fn</span><span class="special">)(</span><span class="identifier">intptr_t</span><span class="special">))</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Precondition:</span></dt> +<dd><p> + A stack is applied to <code class="computeroutput"><span class="special">*</span><span class="identifier">fc</span></code> before <code class="computeroutput"><span class="identifier">make_fcontext</span><span class="special">()</span></code> is called. + </p></dd> +<dt><span class="term">Effects:</span></dt> +<dd><p> + Modifies <code class="computeroutput"><span class="special">*</span><span class="identifier">fc</span></code> + in order to execute <code class="computeroutput"><span class="identifier">fn</span></code> + when the context is activated next. + </p></dd> +</dl> +</div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../context.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../context.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../stack.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/overview.html b/libs/context/doc/html/context/overview.html new file mode 100644 index 0000000000..a6bc1f609d --- /dev/null +++ b/libs/context/doc/html/context/overview.html @@ -0,0 +1,83 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Overview</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="../index.html" title="Context"> +<link rel="next" href="requirements.html" title="Requirements"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="requirements.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.overview"></a><a class="link" href="overview.html" title="Overview">Overview</a> +</h2></div></div></div> +<p> + <span class="bold"><strong>Boost.Context</strong></span> is a foundational library that + provides a sort of cooperative multitasking on a single thread. By providing + an abstraction of the current execution state in the current thread, including + the stack (with local variables) and stack pointer, all registers and CPU flags, + and the instruction pointer, a <span class="emphasis"><em>fcontext_t</em></span> instance represents + a specific point in the application's execution path. This is useful for building + higher-level abstractions, like <span class="emphasis"><em>coroutines</em></span>, <span class="emphasis"><em>cooperative + threads (userland threads)</em></span> or an aquivalent to <a href="http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx" target="_top">C# + keyword <span class="emphasis"><em>yield</em></span></a> in C++. + </p> +<p> + A <span class="emphasis"><em>fcontext_t</em></span> provides the means to suspend the current + execution path and to transfer execution control, thereby permitting another + <span class="emphasis"><em>fcontext_t</em></span> to run on the current thread. This stateful + transfer mechanism enables a <span class="emphasis"><em>fcontext_t</em></span> to suspend execution + from within nested functions and, later, to resume from where it was suspended. + While the execution path represented by a <span class="emphasis"><em>fcontext_t</em></span> only + runs on a single thread, it can be migrated to another thread at any given + time. + </p> +<p> + A context switch between threads requires system calls (involving the OS kernel), + which can cost more than thousand CPU cycles on x86 CPUs. By contrast, transferring + control among them requires only fewer than hundred CPU cycles because it does + not involve system calls as it is done within a single thread. + </p> +<p> + In order to use the classes and functions described here, you can either include + the specific headers specified by the descriptions of each class or function, + or include the master library header: + </p> +<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">context</span><span class="special">/</span><span class="identifier">all</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> +</pre> +<p> + which includes all the other headers in turn. + </p> +<p> + All functions and classes are contained in the namespace <span class="emphasis"><em>boost::ctx</em></span>. + </p> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="requirements.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/performance.html b/libs/context/doc/html/context/performance.html new file mode 100644 index 0000000000..8bdddcbe68 --- /dev/null +++ b/libs/context/doc/html/context/performance.html @@ -0,0 +1,152 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Performance</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="stack/stack_helper.html" title="Helper functions"> +<link rel="next" href="tested.html" title="Tested Platforms"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="stack/stack_helper.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tested.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.performance"></a><a class="link" href="performance.html" title="Performance">Performance</a> +</h2></div></div></div> +<p> + Performance of <span class="bold"><strong>Boost.Context</strong></span> was measured + on the platforms shown in the following table. Performance measurements were + taken using <code class="computeroutput"><span class="identifier">rdtsc</span></code>, with overhead + corrections, on x86 platforms. In each case, stack protection was active, cache + warm-up was accounted for, and the one running thread was pinned to a single + CPU. The code was compiled using the build options, 'variant = release cxxflags + = -DBOOST_DISABLE_ASSERTS'. + </p> +<p> + The numbers in the table are the number of cycles per iteration, based upon + an average computed over 10 iterations. + </p> +<div class="table"> +<a name="context.performance.t0"></a><p class="title"><b>Table 1. Perfomance of context switch</b></p> +<div class="table-contents"><table class="table" summary="Perfomance of context switch"> +<colgroup> +<col> +<col> +<col> +<col> +<col> +</colgroup> +<thead><tr> +<th> + <p> + Platform + </p> + </th> +<th> + <p> + ucontext_t + </p> + </th> +<th> + <p> + fcontext_t with fpu + </p> + </th> +<th> + <p> + fcontext_t without fpu + </p> + </th> +<th> + <p> + boost::function + </p> + </th> +</tr></thead> +<tbody> +<tr> +<td> + <p> + AMD Athlon 64 DualCore 4400+ (32bit Linux) + </p> + </td> +<td> + <p> + 846 cycles + </p> + </td> +<td> + <p> + 65 cycles + </p> + </td> +<td> + <p> + 46 cycles + </p> + </td> +<td> + <p> + 43 cycles + </p> + </td> +</tr> +<tr> +<td> + <p> + Intel Core2 Q6700 (64bit Linux) + </p> + </td> +<td> + <p> + 1472 cycles + </p> + </td> +<td> + <p> + 172 cycles + </p> + </td> +<td> + <p> + 63 cycles + </p> + </td> +<td> + <p> + 60 cycles + </p> + </td> +</tr> +</tbody> +</table></div> +</div> +<br class="table-break"> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="stack/stack_helper.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tested.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/rationale.html b/libs/context/doc/html/context/rationale.html new file mode 100644 index 0000000000..4b85082379 --- /dev/null +++ b/libs/context/doc/html/context/rationale.html @@ -0,0 +1,104 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Rationale</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="tested.html" title="Tested Platforms"> +<link rel="next" href="rationale/other_apis_.html" title="Other APIs"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="tested.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rationale/other_apis_.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.rationale"></a><a class="link" href="rationale.html" title="Rationale">Rationale</a> +</h2></div></div></div> +<div class="toc"><dl> +<dt><span class="section"><a href="rationale/other_apis_.html">Other APIs </a></span></dt> +<dt><span class="section"><a href="rationale/x86_and_floating_point_env.html">x86 and + floating-point env</a></span></dt> +</dl></div> +<h4> +<a name="context.rationale.h0"></a> + <span><a name="context.rationale.no_inline_assembler"></a></span><a class="link" href="rationale.html#context.rationale.no_inline_assembler">No + inline-assembler</a> + </h4> +<p> + Some newer compiler (for instance MSVC 10 for x86_64 and itanium) do not support + inline assembler. <sup>[<a name="context.rationale.f0" href="#ftn.context.rationale.f0" class="footnote">1</a>]</sup>. + </p> +<h4> +<a name="context.rationale.h1"></a> + <span><a name="context.rationale.fcontext_t"></a></span><a class="link" href="rationale.html#context.rationale.fcontext_t">fcontext_t</a> + </h4> +<p> + <span class="bold"><strong>Boost.Context</strong></span> provides the low level API fcontext_t + which is implemented in assembler to provide context swapping operations. fcontext_t + is the part to port to new platforms. + </p> +<div class="note"><table border="0" summary="Note"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> +<th align="left">Note</th> +</tr> +<tr><td align="left" valign="top"><p> + Context switches do not preserve the signal mask on UNIX systems. + </p></td></tr> +</table></div> +<p> + Because the assembler code uses the byte layout of <span class="emphasis"><em>fcontext_t</em></span> + to access its members <span class="emphasis"><em>fcontext_t</em></span> must be a POD. This requires + that <span class="emphasis"><em>fcontext_t</em></span> has only a default constructor, no visibility + keywords (e.g. private, public, protected), no virtual methods and all members + and base clases are PODs too. + </p> +<h4> +<a name="context.rationale.h2"></a> + <span><a name="context.rationale.protecting_the_stack"></a></span><a class="link" href="rationale.html#context.rationale.protecting_the_stack">Protecting + the stack</a> + </h4> +<p> + Because the stack's size is fixed -- there is no support for split stacks yet + -- it is important to protect against exceeding the stack's bounds. Otherwise, + in the best case, overrunning the stack's memory will result in a segmentation + fault or access violation and, in the worst case, the application's memory + will be overwritten. <code class="computeroutput"><span class="identifier">stack_allocator</span></code> + appends a guard page to the stack to help detect overruns. The guard page consumes + no physical memory, but generates a segmentation fault or access violation + on access to the virtual memory addresses within it. + </p> +<div class="footnotes"> +<br><hr width="100" align="left"> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.f0" href="#context.rationale.f0" class="para">1</a>] </sup> + <a href="http://msdn.microsoft.com/en-us/library/4ks26t93.aspx" target="_top">MSDN article + 'Inline Assembler'</a> + </p></div> +</div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="tested.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rationale/other_apis_.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/rationale/other_apis_.html b/libs/context/doc/html/context/rationale/other_apis_.html new file mode 100644 index 0000000000..f86669a1e0 --- /dev/null +++ b/libs/context/doc/html/context/rationale/other_apis_.html @@ -0,0 +1,117 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Other APIs</title> +<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../../index.html" title="Context"> +<link rel="up" href="../rationale.html" title="Rationale"> +<link rel="prev" href="../rationale.html" title="Rationale"> +<link rel="next" href="x86_and_floating_point_env.html" title="x86 and floating-point env"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> +<td align="center"><a href="../../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../rationale.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../rationale.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="x86_and_floating_point_env.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h3 class="title"> +<a name="context.rationale.other_apis_"></a><a class="link" href="other_apis_.html" title="Other APIs">Other APIs </a> +</h3></div></div></div> +<h5> +<a name="context.rationale.other_apis_.h0"></a> + <span><a name="context.rationale.other_apis_.setjmp___longjmp__"></a></span><a class="link" href="other_apis_.html#context.rationale.other_apis_.setjmp___longjmp__">setjmp()/longjmp()</a> + </h5> +<p> + C99 defines <code class="computeroutput"><span class="identifier">setjmp</span><span class="special">()</span></code>/<code class="computeroutput"><span class="identifier">longjmp</span><span class="special">()</span></code> + to provide non-local jumps but it does not require that <span class="emphasis"><em>longjmp()</em></span> + preserves the current stack frame. Therefore, jumping into a function which + was exited via a call to <span class="emphasis"><em>longjmp()</em></span> is undefined <sup>[<a name="context.rationale.other_apis_.f0" href="#ftn.context.rationale.other_apis_.f0" class="footnote">2</a>]</sup>. + </p> +<h5> +<a name="context.rationale.other_apis_.h1"></a> + <span><a name="context.rationale.other_apis_.ucontext_t"></a></span><a class="link" href="other_apis_.html#context.rationale.other_apis_.ucontext_t">ucontext_t</a> + </h5> +<p> + Since POSIX.1-2003 <code class="computeroutput"><span class="identifier">ucontext_t</span></code> + is deprecated and was removed in POSIX.1-2008! The function signature of + <code class="computeroutput"><span class="identifier">makecontext</span><span class="special">()</span></code> + is: + </p> +<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">makecontext</span><span class="special">(</span><span class="identifier">ucontext_t</span> <span class="special">*</span><span class="identifier">ucp</span><span class="special">,</span> <span class="keyword">void</span> <span class="special">(*</span><span class="identifier">func</span><span class="special">)(),</span> <span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="special">...);</span> +</pre> +<p> + The third argument of <code class="computeroutput"><span class="identifier">makecontext</span><span class="special">()</span></code> specifies the number of integer arguments + that follow which will require function pointer cast if <code class="computeroutput"><span class="identifier">func</span></code> + will accept those arguments which is undefined in C99 <sup>[<a name="context.rationale.other_apis_.f1" href="#ftn.context.rationale.other_apis_.f1" class="footnote">3</a>]</sup>. + </p> +<p> + 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 architectures + where pointers are larger than integers. + </p> +<p> + <code class="computeroutput"><span class="identifier">ucontext_t</span></code> preserves signal + mask between context switches which involes system calls consuming a lot + of CPU cycles (ucontext_t is slower by perfomance_link[factor 13x] relative + to <code class="computeroutput"><span class="identifier">fcontext_t</span></code>). + </p> +<h5> +<a name="context.rationale.other_apis_.h2"></a> + <span><a name="context.rationale.other_apis_.windows_fibers"></a></span><a class="link" href="other_apis_.html#context.rationale.other_apis_.windows_fibers">Windows + fibers</a> + </h5> +<p> + A drawback of Windows Fiber API is that <code class="computeroutput"><span class="identifier">CreateFiber</span><span class="special">()</span></code> does not accept a pointer to user allocated + stack space preventing the reuse of stacks for other context instances. Because + the Windows Fiber API requires to call <code class="computeroutput"><span class="identifier">ConvertThreadToFiber</span><span class="special">()</span></code> if <code class="computeroutput"><span class="identifier">SwitchFiber</span><span class="special">()</span></code> is called for a thread which has not been + converted to a fiber. For the same reason <code class="computeroutput"><span class="identifier">ConvertFiberToThread</span><span class="special">()</span></code> must be called after return from <code class="computeroutput"><span class="identifier">SwitchFiber</span><span class="special">()</span></code> + if the thread was forced to be converted to a fiber before (which is inefficient). + </p> +<pre class="programlisting"><span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span> <span class="identifier">is_a_fiber</span><span class="special">()</span> <span class="special">)</span> +<span class="special">{</span> + <span class="identifier">ConvertThreadToFiber</span><span class="special">(</span> <span class="number">0</span><span class="special">);</span> + <span class="identifier">SwitchToFiber</span><span class="special">(</span> <span class="identifier">ctx</span><span class="special">);</span> + <span class="identifier">ConvertFiberToThread</span><span class="special">();</span> +<span class="special">}</span> +</pre> +<p> + If the condition <code class="computeroutput"><span class="identifier">_WIN32_WINNT</span> <span class="special">>=</span> <span class="identifier">_WIN32_WINNT_VISTA</span></code> + is met function <code class="computeroutput"><span class="identifier">IsThreadAFiber</span><span class="special">()</span></code> is provided in order to detect if the current + thread was already converted. Unfortunately Windows XP + SP 2/3 defines + <code class="computeroutput"><span class="identifier">_WIN32_WINNT</span> <span class="special">>=</span> + <span class="identifier">_WIN32_WINNT_VISTA</span></code> without providing + <code class="computeroutput"><span class="identifier">IsThreadAFiber</span><span class="special">()</span></code>. + </p> +<div class="footnotes"> +<br><hr width="100" align="left"> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.other_apis_.f0" href="#context.rationale.other_apis_.f0" class="para">2</a>] </sup> + ISO/IEC 9899:1999, 2005, 7.13.2.1:2 + </p></div> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.other_apis_.f1" href="#context.rationale.other_apis_.f1" class="para">3</a>] </sup> + ISO/IEC 9899:1999, 2005, J.2 + </p></div> +</div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../rationale.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../rationale.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="x86_and_floating_point_env.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/rationale/x86_and_floating_point_env.html b/libs/context/doc/html/context/rationale/x86_and_floating_point_env.html new file mode 100644 index 0000000000..a2118af85c --- /dev/null +++ b/libs/context/doc/html/context/rationale/x86_and_floating_point_env.html @@ -0,0 +1,124 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>x86 and floating-point env</title> +<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../../index.html" title="Context"> +<link rel="up" href="../rationale.html" title="Rationale"> +<link rel="prev" href="other_apis_.html" title="Other APIs"> +<link rel="next" href="../reference.html" title="Reference"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> +<td align="center"><a href="../../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="other_apis_.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../rationale.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../reference.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h3 class="title"> +<a name="context.rationale.x86_and_floating_point_env"></a><a class="link" href="x86_and_floating_point_env.html" title="x86 and floating-point env">x86 and + floating-point env</a> +</h3></div></div></div> +<h5> +<a name="context.rationale.x86_and_floating_point_env.h0"></a> + <span><a name="context.rationale.x86_and_floating_point_env.i386"></a></span><a class="link" href="x86_and_floating_point_env.html#context.rationale.x86_and_floating_point_env.i386">i386</a> + </h5> +<p> + "The FpCsr and the MxCsr register must be saved and restored before + any call or return by any procedure that needs to modify them ..." + <sup>[<a name="context.rationale.x86_and_floating_point_env.f0" href="#ftn.context.rationale.x86_and_floating_point_env.f0" class="footnote">4</a>]</sup>. + </p> +<h5> +<a name="context.rationale.x86_and_floating_point_env.h1"></a> + <span><a name="context.rationale.x86_and_floating_point_env.x86_64"></a></span><a class="link" href="x86_and_floating_point_env.html#context.rationale.x86_and_floating_point_env.x86_64">x86_64</a> + </h5> +<h5> +<a name="context.rationale.x86_and_floating_point_env.h2"></a> + <span><a name="context.rationale.x86_and_floating_point_env.windows"></a></span><a class="link" href="x86_and_floating_point_env.html#context.rationale.x86_and_floating_point_env.windows">Windows</a> + </h5> +<p> + MxCsr - "A callee that modifies any of the nonvolatile fields within + MxCsr must restore them before returning to its caller. Furthermore, a caller + that has modified any of these fields must restore them to their standard + values before invoking a callee ..." <sup>[<a name="context.rationale.x86_and_floating_point_env.f1" href="#ftn.context.rationale.x86_and_floating_point_env.f1" class="footnote">5</a>]</sup>. + </p> +<p> + FpCsr - "A callee that modifies any of the fields within FpCsr must + restore them before returning to its caller. Furthermore, a caller that has + modified any of these fields must restore them to their standard values before + invoking a callee ..." <sup>[<a name="context.rationale.x86_and_floating_point_env.f2" href="#ftn.context.rationale.x86_and_floating_point_env.f2" class="footnote">6</a>]</sup>. + </p> +<p> + "The MMX and floating-point stack registers (MM0-MM7/ST0-ST7) are preserved + across context switches. There is no explicit calling convention for these + registers." <sup>[<a name="context.rationale.x86_and_floating_point_env.f3" href="#ftn.context.rationale.x86_and_floating_point_env.f3" class="footnote">7</a>]</sup>. + </p> +<p> + "The 64-bit Microsoft compiler does not use ST(0)-ST(7)/MM0-MM7". + <sup>[<a name="context.rationale.x86_and_floating_point_env.f4" href="#ftn.context.rationale.x86_and_floating_point_env.f4" class="footnote">8</a>]</sup>. + </p> +<p> + "XMM6-XMM15 must be preserved" <sup>[<a name="context.rationale.x86_and_floating_point_env.f5" href="#ftn.context.rationale.x86_and_floating_point_env.f5" class="footnote">9</a>]</sup> + </p> +<h5> +<a name="context.rationale.x86_and_floating_point_env.h3"></a> + <span><a name="context.rationale.x86_and_floating_point_env.sysv"></a></span><a class="link" href="x86_and_floating_point_env.html#context.rationale.x86_and_floating_point_env.sysv">SysV</a> + </h5> +<p> + "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." <sup>[<a name="context.rationale.x86_and_floating_point_env.f6" href="#ftn.context.rationale.x86_and_floating_point_env.f6" class="footnote">10</a>]</sup>. + </p> +<div class="footnotes"> +<br><hr width="100" align="left"> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.x86_and_floating_point_env.f0" href="#context.rationale.x86_and_floating_point_env.f0" class="para">4</a>] </sup> + 'Calling Conventions', Agner Fog + </p></div> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.x86_and_floating_point_env.f1" href="#context.rationale.x86_and_floating_point_env.f1" class="para">5</a>] </sup> + <a href="http://http://msdn.microsoft.com/en-us/library/yxty7t75.aspx" target="_top">MSDN + article 'MxCsr'</a> + </p></div> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.x86_and_floating_point_env.f2" href="#context.rationale.x86_and_floating_point_env.f2" class="para">6</a>] </sup> + <a href="http://http://msdn.microsoft.com/en-us/library/ms235300.aspx" target="_top">MSDN + article 'FpCsr'</a> + </p></div> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.x86_and_floating_point_env.f3" href="#context.rationale.x86_and_floating_point_env.f3" class="para">7</a>] </sup> + <a href="http://msdn.microsoft.com/en-us/library/a32tsf7t%28VS.80%29.aspx" target="_top">MSDN + article 'Legacy Floating-Point Support'</a> + </p></div> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.x86_and_floating_point_env.f4" href="#context.rationale.x86_and_floating_point_env.f4" class="para">8</a>] </sup> + 'Calling Conventions', Agner Fog + </p></div> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.x86_and_floating_point_env.f5" href="#context.rationale.x86_and_floating_point_env.f5" class="para">9</a>] </sup> + <a href="http://msdn.microsoft.com/en-us/library/9z1stfyw%28v=vs.100%29.aspx" target="_top">MSDN + article 'Register Usage'</a> + </p></div> +<div class="footnote"><p><sup>[<a id="ftn.context.rationale.x86_and_floating_point_env.f6" href="#context.rationale.x86_and_floating_point_env.f6" class="para">10</a>] </sup> + SysV ABI AMD64 Architecture Processor Supplement Draft Version 0.99.4, + 3.2.1 + </p></div> +</div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="other_apis_.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../rationale.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../reference.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/reference.html b/libs/context/doc/html/context/reference.html new file mode 100644 index 0000000000..1cff2438e5 --- /dev/null +++ b/libs/context/doc/html/context/reference.html @@ -0,0 +1,104 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Reference</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="rationale/x86_and_floating_point_env.html" title="x86 and floating-point env"> +<link rel="next" href="todo.html" title="Todo"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="rationale/x86_and_floating_point_env.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="todo.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.reference"></a><a class="link" href="reference.html" title="Reference">Reference</a> +</h2></div></div></div> +<h4> +<a name="context.reference.h0"></a> + <span><a name="context.reference.arm"></a></span><a class="link" href="reference.html#context.reference.arm">ARM</a> + </h4> +<div class="itemizedlist"><ul class="itemizedlist" type="disc"> +<li class="listitem"> + AAPCS ABI: Procedure Call Standard for the ARM Architecture + </li> +<li class="listitem"> + AAPCS/LINUX: ARM GNU/Linux Application Binary Interface Supplement + </li> +</ul></div> +<h4> +<a name="context.reference.h1"></a> + <span><a name="context.reference.mips"></a></span><a class="link" href="reference.html#context.reference.mips">MIPS</a> + </h4> +<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> + O32 ABI: SYSTEM V APPLICATION BINARY INTERFACE, MIPS RISC Processor Supplement + </li></ul></div> +<h4> +<a name="context.reference.h2"></a> + <span><a name="context.reference.powerpc32"></a></span><a class="link" href="reference.html#context.reference.powerpc32">PowerPC32</a> + </h4> +<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> + SYSV ABI: SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement + </li></ul></div> +<h4> +<a name="context.reference.h3"></a> + <span><a name="context.reference.powerpc64"></a></span><a class="link" href="reference.html#context.reference.powerpc64">PowerPC64</a> + </h4> +<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"> + SYSV ABI: PowerPC User Instruction Set Architecture, Book I + </li></ul></div> +<h4> +<a name="context.reference.h4"></a> + <span><a name="context.reference.x86_32"></a></span><a class="link" href="reference.html#context.reference.x86_32">X86-32</a> + </h4> +<div class="itemizedlist"><ul class="itemizedlist" type="disc"> +<li class="listitem"> + SYSV ABI: SYSTEM V APPLICATION BINARY INTERFACE, Intel386TM Architecture + Processor Supplement + </li> +<li class="listitem"> + MS PE: <a href="http://msdn.microsoft.com/en-us/library/k2b2ssfy.aspx" target="_top">Calling + Conventions</a> + </li> +</ul></div> +<h4> +<a name="context.reference.h5"></a> + <span><a name="context.reference.x86_64"></a></span><a class="link" href="reference.html#context.reference.x86_64">X86-64</a> + </h4> +<div class="itemizedlist"><ul class="itemizedlist" type="disc"> +<li class="listitem"> + SYSV ABI: System V Application Binary Interface, AMD64 Architecture Processor + Supplement + </li> +<li class="listitem"> + MS PE: <a href="http://msdn.microsoft.com/en-us/library/7kcdt6fy%28VS.80%29.aspx" target="_top">x64 + Software Conventions</a> + </li> +</ul></div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="rationale/x86_and_floating_point_env.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="todo.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/requirements.html b/libs/context/doc/html/context/requirements.html new file mode 100644 index 0000000000..814e0141fa --- /dev/null +++ b/libs/context/doc/html/context/requirements.html @@ -0,0 +1,59 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Requirements</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="overview.html" title="Overview"> +<link rel="next" href="context.html" title="Context"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="overview.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="context.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.requirements"></a><a class="link" href="requirements.html" title="Requirements">Requirements</a> +</h2></div></div></div> +<p> + <span class="bold"><strong>Boost.Context</strong></span> must be built for the particular + compiler(s) and CPU architecture(s)s being targeted. <span class="bold"><strong>Boost.Context</strong></span> + includes assembly code and, therefore, requires GNU AS for supported POSIX + systems, and MASM for Windows systems. + </p> +<div class="important"><table border="0" summary="Important"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> +<th align="left">Important</th> +</tr> +<tr><td align="left" valign="top"><p> + Please note that address-model=64 must be given to bjam command line on 64bit + Windows (boost-build issue). + </p></td></tr> +</table></div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="overview.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="context.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/stack.html b/libs/context/doc/html/context/stack.html new file mode 100644 index 0000000000..a519a46195 --- /dev/null +++ b/libs/context/doc/html/context/stack.html @@ -0,0 +1,163 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Stack allocation</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="context/boost_fcontext.html" title="Struct fcontext_t and related functions"> +<link rel="next" href="stack/stack_allocator.html" title="Class stack_allocator"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="context/boost_fcontext.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack/stack_allocator.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.stack"></a><a class="link" href="stack.html" title="Stack allocation">Stack allocation</a> +</h2></div></div></div> +<div class="toc"><dl> +<dt><span class="section"><a href="stack/stack_allocator.html">Class <code class="computeroutput"><span class="identifier">stack_allocator</span></code></a></span></dt> +<dt><span class="section"><a href="stack/stack_helper.html">Helper functions</a></span></dt> +</dl></div> +<p> + A <span class="emphasis"><em>fcontext_t</em></span> requires a stack which will be allocated/deallocated + by a <span class="emphasis"><em>StackAllocator</em></span>. <span class="bold"><strong>Boost.Context</strong></span> + uses <code class="computeroutput"><span class="identifier">stack_allocator</span></code> by default + but a customized <code class="computeroutput"><span class="identifier">stack</span> <span class="identifier">allocator</span></code> + can be passed to the context constructor instead. If a context is constructed + it invokes <span class="emphasis"><em>allocate()</em></span> function and by its destruction + the stack gets released by <span class="emphasis"><em>deallocate()</em></span>. + </p> +<h4> +<a name="context.stack.h0"></a> + <span><a name="context.stack._emphasis_stackallocator_concept__emphasis_"></a></span><a class="link" href="stack.html#context.stack._emphasis_stackallocator_concept__emphasis_"><span class="emphasis"><em>StackAllocator + concept</em></span></a> + </h4> +<p> + A <span class="emphasis"><em>StackAllocator</em></span> must satisfy the <span class="emphasis"><em>StackAllocator + concept</em></span> requirements shown in the following table, in which <code class="computeroutput"><span class="identifier">a</span></code> is an object of a <span class="emphasis"><em>StackAllocator</em></span> + type, <code class="computeroutput"><span class="identifier">p</span></code> is a <code class="computeroutput"><span class="keyword">void</span> <span class="special">*</span></code>, and + <code class="computeroutput"><span class="identifier">s</span></code> is a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span></code>: + </p> +<div class="informaltable"><table class="table"> +<colgroup> +<col> +<col> +<col> +</colgroup> +<thead><tr> +<th> + <p> + expression + </p> + </th> +<th> + <p> + return type + </p> + </th> +<th> + <p> + notes + </p> + </th> +</tr></thead> +<tbody> +<tr> +<td> + <p> + <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span> + <span class="identifier">s</span><span class="special">)</span></code> + </p> + </td> +<td> + <p> + <code class="computeroutput"><span class="keyword">void</span> <span class="special">*</span></code> + </p> + </td> +<td> + <p> + returns a pointer to <code class="computeroutput"><span class="identifier">s</span></code> + bytes allocated from the stack + </p> + </td> +</tr> +<tr> +<td> + <p> + <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span> + <span class="identifier">p</span><span class="special">,</span> + <span class="identifier">s</span><span class="special">)</span></code> + </p> + </td> +<td> + <p> + <code class="computeroutput"><span class="keyword">void</span></code> + </p> + </td> +<td> + <p> + deallocates <code class="computeroutput"><span class="identifier">s</span></code> bytes + of memory beginning at <code class="computeroutput"><span class="identifier">p</span></code>, + a pointer previously returned by <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">()</span></code> + </p> + </td> +</tr> +</tbody> +</table></div> +<div class="important"><table border="0" summary="Important"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> +<th align="left">Important</th> +</tr> +<tr><td align="left" valign="top"><p> + The implementation of <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> might include logic to protect against + exceeding the context's available stack size rather than leaving it as undefined + behaviour. + </p></td></tr> +</table></div> +<div class="important"><table border="0" summary="Important"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> +<th align="left">Important</th> +</tr> +<tr><td align="left" valign="top"><p> + Calling <code class="computeroutput"><span class="identifier">deallocate</span><span class="special">()</span></code> + with a pointer not returned by <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> results in undefined behaviour. + </p></td></tr> +</table></div> +<div class="note"><table border="0" summary="Note"> +<tr> +<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> +<th align="left">Note</th> +</tr> +<tr><td align="left" valign="top"><p> + The stack is not required to be aligned; alignment takes place inside <code class="computeroutput"><span class="identifier">make_fcontext</span><span class="special">()</span></code>. + </p></td></tr> +</table></div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="context/boost_fcontext.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack/stack_allocator.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/stack/stack_allocator.html b/libs/context/doc/html/context/stack/stack_allocator.html new file mode 100644 index 0000000000..2a810b23e8 --- /dev/null +++ b/libs/context/doc/html/context/stack/stack_allocator.html @@ -0,0 +1,51 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Class stack_allocator</title> +<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../../index.html" title="Context"> +<link rel="up" href="../stack.html" title="Stack allocation"> +<link rel="prev" href="../stack.html" title="Stack allocation"> +<link rel="next" href="stack_helper.html" title="Helper functions"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> +<td align="center"><a href="../../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../stack.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack_helper.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h3 class="title"> +<a name="context.stack.stack_allocator"></a><a class="link" href="stack_allocator.html" title="Class stack_allocator">Class <code class="computeroutput"><span class="identifier">stack_allocator</span></code></a> +</h3></div></div></div> +<p> + <span class="bold"><strong>Boost.Context</strong></span> provides a <span class="emphasis"><em>StackAllocator</em></span> + <code class="computeroutput"><span class="identifier">stack_allocator</span></code> which models + the <span class="emphasis"><em>StackAllocator concept</em></span> concept. It appends a <span class="emphasis"><em>guard-page</em></span> + 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. + </p> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="../stack.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack_helper.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/stack/stack_helper.html b/libs/context/doc/html/context/stack/stack_helper.html new file mode 100644 index 0000000000..af5494b77d --- /dev/null +++ b/libs/context/doc/html/context/stack/stack_helper.html @@ -0,0 +1,170 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Helper functions</title> +<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../../index.html" title="Context"> +<link rel="up" href="../stack.html" title="Stack allocation"> +<link rel="prev" href="stack_allocator.html" title="Class stack_allocator"> +<link rel="next" href="../performance.html" title="Performance"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> +<td align="center"><a href="../../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="stack_allocator.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../performance.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h3 class="title"> +<a name="context.stack.stack_helper"></a><a class="link" href="stack_helper.html" title="Helper functions">Helper functions</a> +</h3></div></div></div> +<p> + <span class="bold"><strong>Boost.Context</strong></span> provides easy access to the + stack related limits defined by the environment. + </p> +<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">default_stacksize</span><span class="special">();</span> + +<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">minimum_stacksize</span><span class="special">();</span> + +<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">maximum_stacksize</span><span class="special">();</span> + +<span class="keyword">bool</span> <span class="identifier">is_stack_unbound</span><span class="special">();</span> + +<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">pagesize</span><span class="special">();</span> + +<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">page_count</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">stacksize</span><span class="special">);</span> +</pre> +<h5> +<a name="context.stack.stack_helper.h0"></a> + <span><a name="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_stacksize__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="stack_helper.html#context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_stacksize__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> + <span class="identifier">default_stacksize</span><span class="special">()</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Returns:</span></dt> +<dd><p> + Returns a default stack size, which may be platform specific. The present + implementation returns a value of 256 kB. + </p></dd> +</dl> +</div> +<h5> +<a name="context.stack.stack_helper.h1"></a> + <span><a name="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_stacksize__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="stack_helper.html#context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_stacksize__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> + <span class="identifier">minimum_stacksize</span><span class="special">()</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Returns:</span></dt> +<dd><p> + Returns the minimum size in bytes of stack defined by the environment. + </p></dd> +<dt><span class="term">Throws:</span></dt> +<dd><p> + Nothing. + </p></dd> +</dl> +</div> +<h5> +<a name="context.stack.stack_helper.h2"></a> + <span><a name="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_stacksize__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="stack_helper.html#context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_stacksize__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> + <span class="identifier">maximum_stacksize</span><span class="special">()</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Preconditions:</span></dt> +<dd><p> + <code class="computeroutput"><span class="identifier">is_stack_unbound</span><span class="special">()</span></code> + returns <code class="computeroutput"><span class="keyword">false</span></code>. + </p></dd> +<dt><span class="term">Returns:</span></dt> +<dd><p> + Returns the maximum size in bytes of stack defined by the environment. + </p></dd> +<dt><span class="term">Throws:</span></dt> +<dd><p> + Nothing. + </p></dd> +</dl> +</div> +<h5> +<a name="context.stack.stack_helper.h3"></a> + <span><a name="context.stack.stack_helper._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_stack_unbound__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="stack_helper.html#context.stack.stack_helper._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_stack_unbound__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="keyword">bool</span> <span class="identifier">is_stack_unbound</span><span class="special">()</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Returns:</span></dt> +<dd><p> + Returns <code class="computeroutput"><span class="keyword">true</span></code> if the environment + defines no limit for the size of a stack. + </p></dd> +<dt><span class="term">Throws:</span></dt> +<dd><p> + Nothing. + </p></dd> +</dl> +</div> +<h5> +<a name="context.stack.stack_helper.h4"></a> + <span><a name="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__pagesize__phrase__phrase_role__special______phrase___code_"></a></span><a class="link" href="stack_helper.html#context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__pagesize__phrase__phrase_role__special______phrase___code_"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> + <span class="identifier">pagesize</span><span class="special">()</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Returns:</span></dt> +<dd><p> + Returns how many bytes the operating system allocates for one page. + </p></dd> +<dt><span class="term">Throws:</span></dt> +<dd><p> + Nothing. + </p></dd> +</dl> +</div> +<h5> +<a name="context.stack.stack_helper.h5"></a> + <span><a name="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_count__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stacksize__phrase__phrase_role__special_____phrase___code_"></a></span><a class="link" href="stack_helper.html#context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_count__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stacksize__phrase__phrase_role__special_____phrase___code_"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> + <span class="identifier">page_count</span><span class="special">(</span> + <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">stacksize</span><span class="special">)</span></code></a> + </h5> +<div class="variablelist"> +<p class="title"><b></b></p> +<dl> +<dt><span class="term">Returns:</span></dt> +<dd><p> + Returns how many pages have to be allocated for a stack of <code class="computeroutput"><span class="identifier">stacksize</span></code> bytes. + </p></dd> +<dt><span class="term">Throws:</span></dt> +<dd><p> + Nothing. + </p></dd> +</dl> +</div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="stack_allocator.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../performance.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/tested.html b/libs/context/doc/html/context/tested.html new file mode 100644 index 0000000000..e2fe446b10 --- /dev/null +++ b/libs/context/doc/html/context/tested.html @@ -0,0 +1,295 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Tested Platforms</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="performance.html" title="Performance"> +<link rel="next" href="rationale.html" title="Rationale"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="performance.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rationale.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.tested"></a><a class="link" href="tested.html" title="Tested Platforms">Tested Platforms</a> +</h2></div></div></div> +<div class="informaltable"><table class="table"> +<colgroup> +<col> +<col> +<col> +<col> +</colgroup> +<thead><tr> +<th> + <p> + Platform + </p> + </th> +<th> + <p> + OS + </p> + </th> +<th> + <p> + Compiler + </p> + </th> +<th> + <p> + ABI + </p> + </th> +</tr></thead> +<tbody> +<tr> +<td> + <p> + ARM (ARM926EJ-S) + </p> + </td> +<td> + <p> + Debian GNU/Linux (Lenny) + </p> + </td> +<td> + <p> + GCC 4.4.4 + </p> + </td> +<td> + <p> + ARM APCS (Linux) + </p> + </td> +</tr> +<tr> +<td> + <p> + MIPS (MIPS 24K) + </p> + </td> +<td> + <p> + Debian GNU/Linux (Lenny) + </p> + </td> +<td> + <p> + GCC 4.3.2 + </p> + </td> +<td> + <p> + O32 + </p> + </td> +</tr> +<tr> +<td> + <p> + MIPS (O2 / MIPS R5000) + </p> + </td> +<td> + <p> + Debian GNU/Linux (Lenny) + </p> + </td> +<td> + <p> + GCC 4.3.2 + </p> + </td> +<td> + <p> + O32 + </p> + </td> +</tr> +<tr> +<td> + <p> + PowerPC (7400) + </p> + </td> +<td> + <p> + Debian GNU/Linux (Lenny) + </p> + </td> +<td> + <p> + GCC 4.3.2 + </p> + </td> +<td> + <p> + SYSV + </p> + </td> +</tr> +<tr> +<td> + <p> + X86_64 (Intel Core2 Quad) + </p> + </td> +<td> + <p> + Ubuntu GNU/Linux (Lucid Lynx) + </p> + </td> +<td> + <p> + GCC 4.4.3 + </p> + </td> +<td> + <p> + SYSV + </p> + </td> +</tr> +<tr> +<td> + <p> + X86_64 + </p> + </td> +<td> + <p> + Windows 7 + </p> + </td> +<td> + <p> + MS VC 10.0 + </p> + </td> +<td> + <p> + PE + </p> + </td> +</tr> +<tr> +<td> + <p> + I386 + </p> + </td> +<td> + <p> + Debian GNU/Linux (Lenny) + </p> + </td> +<td> + <p> + GCC 4.4.3 + </p> + </td> +<td> + <p> + SYSV + </p> + </td> +</tr> +<tr> +<td> + <p> + I386 + </p> + </td> +<td> + <p> + FreeBSD 8.0 + </p> + </td> +<td> + <p> + GCC 4.2.1 + </p> + </td> +<td> + <p> + SYSV + </p> + </td> +</tr> +<tr> +<td> + <p> + I386 + </p> + </td> +<td> + <p> + OpenSolaris 2009.06 + </p> + </td> +<td> + <p> + GCC 4.3.2 + </p> + </td> +<td> + <p> + SYSV + </p> + </td> +</tr> +<tr> +<td> + <p> + I386 + </p> + </td> +<td> + <p> + Windows XP + </p> + </td> +<td> + <p> + MSVC 9.0 + </p> + </td> +<td> + <p> + PE + </p> + </td> +</tr> +</tbody> +</table></div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="performance.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rationale.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/context/todo.html b/libs/context/doc/html/context/todo.html new file mode 100644 index 0000000000..c6c1b329a1 --- /dev/null +++ b/libs/context/doc/html/context/todo.html @@ -0,0 +1,51 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Todo</title> +<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="../index.html" title="Context"> +<link rel="up" href="../index.html" title="Context"> +<link rel="prev" href="reference.html" title="Reference"> +<link rel="next" href="acknowledgements.html" title="Acknowledgments"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> +<td align="center"><a href="../../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="reference.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgements.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +<div class="section"> +<div class="titlepage"><div><div><h2 class="title" style="clear: both"> +<a name="context.todo"></a><a class="link" href="todo.html" title="Todo">Todo</a> +</h2></div></div></div> +<div class="itemizedlist"><ul class="itemizedlist" type="disc"> +<li class="listitem"> + provide support for SPARC + </li> +<li class="listitem"> + support split-stack feature from gcc/gold linker + </li> +</ul></div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"></td> +<td align="right"><div class="copyright-footer">Copyright © 2009 Oliver Kowalke<p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></td> +</tr></table> +<hr> +<div class="spirit-nav"> +<a accesskey="p" href="reference.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgements.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> +</div> +</body> +</html> diff --git a/libs/context/doc/html/index.html b/libs/context/doc/html/index.html new file mode 100644 index 0000000000..e540e54353 --- /dev/null +++ b/libs/context/doc/html/index.html @@ -0,0 +1,72 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> +<title>Context</title> +<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css"> +<meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> +<link rel="home" href="index.html" title="Context"> +<link rel="next" href="context/overview.html" title="Overview"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> +<table cellpadding="2" width="100%"><tr> +<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td> +<td align="center"><a href="../../../../index.html">Home</a></td> +<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td> +<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> +<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> +<td align="center"><a href="../../../../more/index.htm">More</a></td> +</tr></table> +<hr> +<div class="spirit-nav"><a accesskey="n" href="context/overview.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div> +<div class="article"> +<div class="titlepage"> +<div> +<div><h2 class="title"> +<a name="context"></a>Context</h2></div> +<div><div class="authorgroup"><div class="author"><h3 class="author"> +<span class="firstname">Oliver</span> <span class="surname">Kowalke</span> +</h3></div></div></div> +<div><p class="copyright">Copyright © 2009 Oliver Kowalke</p></div> +<div><div class="legalnotice"> +<a name="context.legal"></a><p> + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) + </p> +</div></div> +</div> +<hr> +</div> +<div class="toc"> +<p><b>Table of Contents</b></p> +<dl> +<dt><span class="section"><a href="context/overview.html">Overview</a></span></dt> +<dt><span class="section"><a href="context/requirements.html">Requirements</a></span></dt> +<dt><span class="section"><a href="context/context.html">Context</a></span></dt> +<dd><dl><dt><span class="section"><a href="context/context/boost_fcontext.html">Struct <code class="computeroutput"><span class="identifier">fcontext_t</span></code> and related functions</a></span></dt></dl></dd> +<dt><span class="section"><a href="context/stack.html">Stack allocation</a></span></dt> +<dd><dl> +<dt><span class="section"><a href="context/stack/stack_allocator.html">Class <code class="computeroutput"><span class="identifier">stack_allocator</span></code></a></span></dt> +<dt><span class="section"><a href="context/stack/stack_helper.html">Helper functions</a></span></dt> +</dl></dd> +<dt><span class="section"><a href="context/performance.html">Performance</a></span></dt> +<dt><span class="section"><a href="context/tested.html">Tested Platforms</a></span></dt> +<dt><span class="section"><a href="context/rationale.html">Rationale</a></span></dt> +<dd><dl> +<dt><span class="section"><a href="context/rationale/other_apis_.html">Other APIs </a></span></dt> +<dt><span class="section"><a href="context/rationale/x86_and_floating_point_env.html">x86 and + floating-point env</a></span></dt> +</dl></dd> +<dt><span class="section"><a href="context/reference.html">Reference</a></span></dt> +<dt><span class="section"><a href="context/todo.html">Todo</a></span></dt> +<dt><span class="section"><a href="context/acknowledgements.html">Acknowledgments</a></span></dt> +</dl> +</div> +</div> +<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> +<td align="left"><p><small>Last revised: August 15, 2012 at 23:36:42 GMT</small></p></td> +<td align="right"><div class="copyright-footer"></div></td> +</tr></table> +<hr> +<div class="spirit-nav"><a accesskey="n" href="context/overview.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div> +</body> +</html> diff --git a/libs/context/doc/html/standalone_HTML.manifest b/libs/context/doc/html/standalone_HTML.manifest new file mode 100644 index 0000000000..3ffe9abe75 --- /dev/null +++ b/libs/context/doc/html/standalone_HTML.manifest @@ -0,0 +1,16 @@ +index.html +context/overview.html +context/requirements.html +context/context.html +context/context/boost_fcontext.html +context/stack.html +context/stack/stack_allocator.html +context/stack/stack_helper.html +context/performance.html +context/tested.html +context/rationale.html +context/rationale/other_apis_.html +context/rationale/x86_and_floating_point_env.html +context/reference.html +context/todo.html +context/acknowledgements.html diff --git a/libs/context/doc/overview.qbk b/libs/context/doc/overview.qbk new file mode 100644 index 0000000000..d08381f635 --- /dev/null +++ b/libs/context/doc/overview.qbk @@ -0,0 +1,42 @@ +[/ + 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:overview Overview] + +__boost_context__ is a foundational library that provides a sort of cooperative +multitasking on a single thread. By providing an abstraction of the current +execution state in the current thread, including the stack (with local +variables) and stack pointer, all registers and CPU flags, and the instruction +pointer, a __fcontext__ instance represents a specific point in the application's +execution path. This is useful for building higher-level abstractions, like +__coroutines__, __coop_threads__ or an aquivalent to +[@http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx C# keyword __yield__] +in C++. + +A __fcontext__ provides the means to suspend the current execution path and to +transfer execution control, thereby permitting another __fcontext__ to run on the +current thread. This stateful transfer mechanism enables a __fcontext__ to +suspend execution from within nested functions and, later, to resume from where +it was suspended. While the execution path represented by a __fcontext__ only +runs on a single thread, it can be migrated to another thread at any given time. + +A context switch between threads requires system calls (involving the OS +kernel), which can cost more than thousand CPU cycles on x86 CPUs. By contrast, +transferring control among them requires only fewer than hundred CPU cycles because +it does not involve system calls as it is done within a single thread. + +In order to use the classes and functions described here, you can either include +the specific headers specified by the descriptions of each class or function, or +include the master library header: + + #include <boost/context/all.hpp> + +which includes all the other headers in turn. + +All functions and classes are contained in the namespace __context_ns__. + +[endsect] diff --git a/libs/context/doc/performance.qbk b/libs/context/doc/performance.qbk new file mode 100644 index 0000000000..f6d01fe1a0 --- /dev/null +++ b/libs/context/doc/performance.qbk @@ -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 +] + +[section:performance Performance] + +Performance of __boost_context__ was measured on the platforms shown in the +following table. Performance measurements were taken using `rdtsc`, with +overhead corrections, on x86 platforms. In each case, stack protection was +active, cache warm-up was accounted for, and the one running thread was pinned +to a single CPU. The code was compiled using the build options, +'variant = release cxxflags = -DBOOST_DISABLE_ASSERTS'. + +The numbers in the table are the number of cycles per iteration, based upon an +average computed over 10 iterations. + +[table Perfomance of context switch + [[Platform] [ucontext_t] [fcontext_t with fpu] [fcontext_t without fpu] [boost::function]] + [ + [AMD Athlon 64 DualCore 4400+ (32bit Linux)] + [846 cycles] + [65 cycles] + [46 cycles] + [43 cycles] + ] + [ + [Intel Core2 Q6700 (64bit Linux)] + [1472 cycles] + [172 cycles] + [63 cycles] + [60 cycles] + ] +] + + +[endsect] diff --git a/libs/context/doc/rationale.qbk b/libs/context/doc/rationale.qbk new file mode 100644 index 0000000000..75e8dfb746 --- /dev/null +++ b/libs/context/doc/rationale.qbk @@ -0,0 +1,148 @@ +[/ + 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:rationale Rationale] + +[heading No inline-assembler] + +Some newer compiler (for instance MSVC 10 for x86_64 and itanium) do not +support inline assembler. +[footnote [@http://msdn.microsoft.com/en-us/library/4ks26t93.aspx MSDN article +'Inline Assembler']]. + + +[heading fcontext_t] + +__boost_context__ provides the low level API fcontext_t which is +implemented in assembler to provide context swapping operations. +fcontext_t is the part to port to new platforms. + +[note Context switches do not preserve the signal mask on UNIX systems.] + +Because the assembler code uses the byte layout of __fcontext__ to access +its members __fcontext__ must be a POD. This requires that __fcontext__ has only a +default constructor, no visibility keywords (e.g. private, public, protected), no +virtual methods and all members and base clases are PODs too. + + +[heading Protecting the stack] + +Because the stack's size is fixed -- there is no support for split stacks yet -- it +is important to protect against exceeding the stack's bounds. Otherwise, in the +best case, overrunning the stack's memory will result in a segmentation fault or +access violation and, in the worst case, the application's memory will be +overwritten. `stack_allocator` appends a guard page to the stack to help detect +overruns. The guard page consumes no physical memory, but generates a +segmentation fault or access violation on access to the virtual memory addresses +within it. + + +[section Other APIs ] + +[heading setjmp()/longjmp()] + +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 ISO/IEC 9899:1999, 2005, 7.13.2.1:2]. + + +[heading ucontext_t] + +Since POSIX.1-2003 `ucontext_t` is deprecated and was removed in POSIX.1-2008! +The function signature of `makecontext()` is: + + void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...); + +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 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 +architectures where pointers are larger than integers. + +`ucontext_t` preserves signal mask between context switches which involes system +calls consuming a lot of CPU cycles (ucontext_t is slower by +perfomance_link[factor 13x] relative to `fcontext_t`). + + +[heading Windows fibers] + +A drawback of Windows Fiber API is that `CreateFiber()` does not accept a +pointer to user allocated stack space preventing the reuse of stacks for other +context instances. Because the Windows Fiber API requires to call +`ConvertThreadToFiber()` if `SwitchFiber()` is called for a thread which has not +been converted to a fiber. For the same reason `ConvertFiberToThread()` +must be called after return from `SwitchFiber()` if the thread was forced to be +converted to a fiber before (which is inefficient). + + if ( ! is_a_fiber() ) + { + ConvertThreadToFiber( 0); + SwitchToFiber( ctx); + ConvertFiberToThread(); + } + +If the condition `_WIN32_WINNT >= _WIN32_WINNT_VISTA` is met function +`IsThreadAFiber()` is provided in order to detect if the current thread was +already converted. Unfortunately Windows XP + SP 2/3 defines +`_WIN32_WINNT >= _WIN32_WINNT_VISTA` without providing `IsThreadAFiber()`. + +[endsect] + + +[section x86 and floating-point env] + +[heading i386] + +"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 'Calling Conventions', Agner Fog]. + + +[heading x86_64] + +[heading Windows] + +MxCsr - "A callee that modifies any of the nonvolatile fields within MxCsr must restore +them before returning to its caller. Furthermore, a caller that has modified any +of these fields must restore them to their standard values before invoking a callee ..." +[footnote [@http://http://msdn.microsoft.com/en-us/library/yxty7t75.aspx MSDN article +'MxCsr']]. + +FpCsr - "A callee that modifies any of the fields within FpCsr must restore them before +returning to its caller. Furthermore, a caller that has modified any of these +fields must restore them to their standard values before invoking a callee ..." +[footnote [@http://http://msdn.microsoft.com/en-us/library/ms235300.aspx MSDN article +'FpCsr']]. + +"The MMX and floating-point stack registers (MM0-MM7/ST0-ST7) are preserved across +context switches. There is no explicit calling convention for these registers." +[footnote [@http://msdn.microsoft.com/en-us/library/a32tsf7t%28VS.80%29.aspx MSDN article +'Legacy Floating-Point Support']]. + +"The 64-bit Microsoft compiler does not use ST(0)-ST(7)/MM0-MM7". +[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 +article 'Register Usage']] + + +[heading SysV] + +"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 SysV ABI AMD64 Architecture Processor Supplement Draft Version 0.99.4, 3.2.1]. + +[endsect] + + +[endsect] diff --git a/libs/context/doc/reference.qbk b/libs/context/doc/reference.qbk new file mode 100644 index 0000000000..d7ab1ddbd0 --- /dev/null +++ b/libs/context/doc/reference.qbk @@ -0,0 +1,43 @@ +[/ + 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:reference Reference] + +[heading ARM] + +* AAPCS ABI: Procedure Call Standard for the ARM Architecture +* AAPCS/LINUX: ARM GNU/Linux Application Binary Interface Supplement + + +[heading MIPS] + +* O32 ABI: SYSTEM V APPLICATION BINARY INTERFACE, MIPS RISC Processor Supplement + + +[heading PowerPC32] + +* SYSV ABI: SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement + + +[heading PowerPC64] + +* SYSV ABI: PowerPC User Instruction Set Architecture, Book I + + +[heading X86-32] + +* 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: 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] + + +[endsect] diff --git a/libs/context/doc/requirements.qbk b/libs/context/doc/requirements.qbk new file mode 100644 index 0000000000..aa5a656777 --- /dev/null +++ b/libs/context/doc/requirements.qbk @@ -0,0 +1,18 @@ +[/ + 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:requirements Requirements] + +__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. + +[important Please note that address-model=64 must be given to bjam command line +on 64bit Windows (boost-build issue).] + +[endsect] diff --git a/libs/context/doc/stack.qbk b/libs/context/doc/stack.qbk new file mode 100644 index 0000000000..306ca27842 --- /dev/null +++ b/libs/context/doc/stack.qbk @@ -0,0 +1,116 @@ +[/ + 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:stack Stack allocation] + +A __fcontext__ requires a stack which will be allocated/deallocated +by a __stack_allocator__. +__boost_context__ uses `stack_allocator` by default but a +customized `stack allocator` can be passed to the context constructor +instead. +If a context is constructed it invokes __stack_alloc__ function and by its +destruction the stack gets released by __stack_dealloc__. + +[heading __stack_allocator_concept__] +A __stack_allocator__ must satisfy the __stack_allocator_concept__ requirements +shown in the following table, in which `a` is an object of a +__stack_allocator__ type, `p` is a `void *`, and `s` is a `std::size_t`: + +[table + [[expression][return type][notes]] + [ + [`a.allocate( s)`] + [`void *`] + [returns a pointer to `s` bytes allocated from the stack] + ] + [ + [`a.deallocate( p, s)`] + [`void`] + [deallocates `s` bytes of memory beginning at `p`, + a pointer previously returned by `a.allocate()`] + ] +] + +[important The implementation of `allocate()` might include logic to protect +against exceeding the context's available stack size rather than leaving it as +undefined behaviour.] + +[important Calling `deallocate()` with a pointer not returned by `allocate()` +results in undefined behaviour.] + +[note The stack is not required to be aligned; alignment takes place inside +`make_fcontext()`.] + + +[section:stack_allocator Class `stack_allocator`] + +__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. + +[endsect] + + +[section:stack_helper Helper functions] + +__boost_context__ provides easy access to the stack related limits defined by +the environment. + + std::size_t default_stacksize(); + + std::size_t minimum_stacksize(); + + std::size_t maximum_stacksize(); + + bool is_stack_unbound(); + + std::size_t pagesize(); + + std::size_t page_count( std::size_t stacksize); + +[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.]] +] + +[heading `std::size_t minimum_stacksize()`] +[variablelist +[[Returns:] [Returns the minimum size in bytes of stack defined by the environment.]] +[[Throws:] [Nothing.]] +] + +[heading `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 `bool is_stack_unbound()`] +[variablelist +[[Returns:] [Returns `true` if the environment defines no limit for the size of a stack.]] +[[Throws:] [Nothing.]] +] + +[heading `std::size_t pagesize()`] +[variablelist +[[Returns:] [Returns how many bytes the operating system allocates for one page.]] +[[Throws:] [Nothing.]] +] + +[heading `std::size_t page_count( std::size_t stacksize)`] +[variablelist +[[Returns:] [Returns how many pages have to be allocated for a stack of `stacksize` bytes.]] +[[Throws:] [Nothing.]] +] + +[endsect] + +[endsect] diff --git a/libs/context/doc/tested.qbk b/libs/context/doc/tested.qbk new file mode 100644 index 0000000000..08a20074d8 --- /dev/null +++ b/libs/context/doc/tested.qbk @@ -0,0 +1,74 @@ +[/ + 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:tested Tested Platforms] + +[table + [[Platform] [OS] [Compiler] [ABI]] + [ + [ARM (ARM926EJ-S)] + [Debian GNU/Linux (Lenny)] + [GCC 4.4.4] + [ARM APCS (Linux)] + ] + [ + [MIPS (MIPS 24K)] + [Debian GNU/Linux (Lenny)] + [GCC 4.3.2] + [O32] + ] + [ + [MIPS (O2 / MIPS R5000)] + [Debian GNU/Linux (Lenny)] + [GCC 4.3.2] + [O32] + ] + [ + [PowerPC (7400)] + [Debian GNU/Linux (Lenny)] + [GCC 4.3.2] + [SYSV] + ] + [ + [X86_64 (Intel Core2 Quad)] + [Ubuntu GNU/Linux (Lucid Lynx)] + [GCC 4.4.3] + [SYSV] + ] + [ + [X86_64] + [Windows 7] + [MS VC 10.0] + [PE] + ] + [ + [I386] + [Debian GNU/Linux (Lenny)] + [GCC 4.4.3] + [SYSV] + ] + [ + [I386] + [FreeBSD 8.0] + [GCC 4.2.1] + [SYSV] + ] + [ + [I386] + [OpenSolaris 2009.06] + [GCC 4.3.2] + [SYSV] + ] + [ + [I386] + [Windows XP] + [MSVC 9.0] + [PE] + ] +] + +[endsect] diff --git a/libs/context/doc/todo.qbk b/libs/context/doc/todo.qbk new file mode 100644 index 0000000000..42aac14048 --- /dev/null +++ b/libs/context/doc/todo.qbk @@ -0,0 +1,13 @@ +[/ + 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:todo Todo] + +* provide support for SPARC +* support split-stack feature from gcc/gold linker + +[endsect] diff --git a/libs/context/example/Jamfile.v2 b/libs/context/example/Jamfile.v2 new file mode 100644 index 0000000000..e08943f9c7 --- /dev/null +++ b/libs/context/example/Jamfile.v2 @@ -0,0 +1,49 @@ +# Boost.Context Library Examples Jamfile + +# 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) + +# For more information, see http://www.boost.org/ + +import common ; +import feature ; +import indirect ; +import modules ; +import os ; +import toolset ; + +if [ os.name ] = SOLARIS +{ + lib socket ; + lib nsl ; +} +else if [ os.name ] = NT +{ + lib ws2_32 ; + lib mswsock ; +} +else if [ os.name ] = HPUX +{ + lib ipv6 ; +} + +project boost/context/example + : requirements + <library>/boost/context//boost_context + <define>BOOST_ALL_NO_LIB=1 + <link>static + ; + +exe jump + : jump.cpp + ; + +exe exit + : exit.cpp + ; + +exe transfer + : transfer.cpp + ; diff --git a/libs/context/example/exit.cpp b/libs/context/example/exit.cpp new file mode 100644 index 0000000000..638d9f4a9e --- /dev/null +++ b/libs/context/example/exit.cpp @@ -0,0 +1,57 @@ + +// 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) + +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <vector> + +#include <boost/assert.hpp> +#include <boost/context/all.hpp> + +namespace ctx = boost::ctx; + +ctx::fcontext_t 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: 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); + BOOST_ASSERT( false && ! "f2: never returns"); +} + +int main( int argc, char * argv[]) +{ + ctx::fcontext_t fcm; + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize()); + fc1.fc_stack.limit = + static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc1, f1); + + fc2.fc_stack.base = alloc.allocate(ctx::minimum_stacksize()); + fc2.fc_stack.limit = + static_cast< char * >( fc2.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc2, 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"); + + return EXIT_SUCCESS; +} diff --git a/libs/context/example/jump.cpp b/libs/context/example/jump.cpp new file mode 100644 index 0000000000..7520b2fcd5 --- /dev/null +++ b/libs/context/example/jump.cpp @@ -0,0 +1,56 @@ + +// 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) + +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <vector> + +#include <boost/assert.hpp> +#include <boost/context/all.hpp> + +namespace ctx = boost::ctx; + +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: return" << std::endl; + 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); + BOOST_ASSERT( false && ! "f2: never returns"); +} + +int main( int argc, char * argv[]) +{ + ctx::stack_allocator alloc1, alloc2; + + fc1.fc_stack.base = alloc1.allocate(ctx::minimum_stacksize()); + fc1.fc_stack.limit = + static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc1, f1); + + fc2.fc_stack.base = alloc2.allocate(ctx::minimum_stacksize()); + fc2.fc_stack.limit = + static_cast< char * >( fc2.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc2, f2); + + std::cout << "main: call start_fcontext( & fcm, & fc1, 0)" << std::endl; + ctx::jump_fcontext( & fcm, & fc1, 0); + + std::cout << "main: done" << std::endl; + + return EXIT_SUCCESS; +} diff --git a/libs/context/example/transfer.cpp b/libs/context/example/transfer.cpp new file mode 100644 index 0000000000..6837faf01d --- /dev/null +++ b/libs/context/example/transfer.cpp @@ -0,0 +1,51 @@ + +// 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) + +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <utility> +#include <vector> + +#include <boost/assert.hpp> +#include <boost/context/all.hpp> + +namespace ctx = boost::ctx; + +ctx::fcontext_t fc1, fcm; + +typedef std::pair< int, int > pair_t; + +void f1( intptr_t param) +{ + pair_t * p = ( pair_t *) param; + + 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) ); +} + +int main( int argc, char * argv[]) +{ + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize()); + fc1.fc_stack.limit = + static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc1, f1); + + pair_t p( std::make_pair( 2, 7) ); + 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); + std::cout << p.first << " + " << p.second << " == " << res << std::endl; + + std::cout << "main: done" << std::endl; + + return EXIT_SUCCESS; +} diff --git a/libs/context/index.html b/libs/context/index.html new file mode 100644 index 0000000000..0ade6cbd26 --- /dev/null +++ b/libs/context/index.html @@ -0,0 +1,14 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=doc/html/index.html"> +</head> +<body> +Automatic redirection failed, please go to +<a href="doc/html/index.html">doc/html/index.html</a> +<hr> +<p>© Copyright Beman Dawes, 2001</p> +<p> Distributed under the Boost Software +License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> +www.boost.org/LICENSE_1_0.txt</a>)</p> +</body> +</html> diff --git a/libs/context/performance/Jamfile.v2 b/libs/context/performance/Jamfile.v2 new file mode 100644 index 0000000000..108c0e1ce1 --- /dev/null +++ b/libs/context/performance/Jamfile.v2 @@ -0,0 +1,64 @@ + +# 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) + +# For more information, see http://www.boost.org/ + +import common ; +import feature ; +import indirect ; +import modules ; +import os ; +import toolset ; + +project boost/context/performance + : requirements + <library>/boost/context//boost_context + <link>static + <linkflags>"-lrt" + <threading>single + ; + +alias sources + : performance.cpp + bind_processor_aix.cpp + : <target-os>aix + ; + +alias sources + : performance.cpp + bind_processor_freebsd.cpp + : <target-os>freebsd + ; + +alias sources + : performance.cpp + bind_processor_hpux.cpp + : <target-os>hpux + ; + +alias sources + : performance.cpp + bind_processor_linux.cpp + : <target-os>linux + ; + +alias sources + : performance.cpp + bind_processor_solaris.cpp + : <target-os>solaris + ; + +alias sources + : performance.cpp + bind_processor_windows.cpp + : <target-os>windows + ; + +explicit sources ; + +exe performance + : sources + ; diff --git a/libs/context/performance/bind_processor.hpp b/libs/context/performance/bind_processor.hpp new file mode 100644 index 0000000000..f89b507445 --- /dev/null +++ b/libs/context/performance/bind_processor.hpp @@ -0,0 +1,12 @@ + +// 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 BIND_TO_PROCESSOR_H +#define BIND_TO_PROCESSOR_H + +void bind_to_processor( unsigned int n); + +#endif // BIND_TO_PROCESSOR_H diff --git a/libs/context/performance/bind_processor_aix.cpp b/libs/context/performance/bind_processor_aix.cpp new file mode 100644 index 0000000000..7ddc2eb42c --- /dev/null +++ b/libs/context/performance/bind_processor_aix.cpp @@ -0,0 +1,25 @@ + +// 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) + +#include "bind_processor.hpp" + +extern "C" +{ +#include <sys/processor.h> +#include <sys/thread.h> +} + +#include <stdexcept> + +#include <boost/config/abi_prefix.hpp> + +void bind_to_processor( unsigned int n) +{ + if ( ::bindprocessor( BINDTHREAD, ::thread_self(), static_cast< cpu_t >( n) ) == -1) + throw std::runtime_error("::bindprocessor() failed"); +} + +#include <boost/config/abi_suffix.hpp> diff --git a/libs/context/performance/bind_processor_freebsd.cpp b/libs/context/performance/bind_processor_freebsd.cpp new file mode 100644 index 0000000000..7e28b70676 --- /dev/null +++ b/libs/context/performance/bind_processor_freebsd.cpp @@ -0,0 +1,29 @@ + +// 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) + +#include "bind_processor.hpp" + +extern "C" +{ +#include <sys/param.h> +#include <sys/cpuset.h> +} + +#include <stdexcept> + +#include <boost/config/abi_prefix.hpp> + +void bind_to_processor( unsigned int n) +{ + cpuset_t cpuset; + CPU_ZERO( & cpuset); + CPU_SET( n, & cpuset); + + if ( ::cpuset_setaffinity( CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof( cpuset), & cpuset) == -1) + throw std::runtime_error("::cpuset_setaffinity() failed"); +} + +#include <boost/config/abi_suffix.hpp> diff --git a/libs/context/performance/bind_processor_hpux.cpp b/libs/context/performance/bind_processor_hpux.cpp new file mode 100644 index 0000000000..af33c1125c --- /dev/null +++ b/libs/context/performance/bind_processor_hpux.cpp @@ -0,0 +1,31 @@ + +// 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) + +#include "bind_processor.hpp" + +extern "C" +{ +#include <sys/pthread.h> +} + +#include <stdexcept> + +#include <boost/config/abi_prefix.hpp> + +void bind_to_processor( unsigned int n) +{ + ::pthread_spu_t spu; + int errno_( + ::pthread_processor_bind_np( + PTHREAD_BIND_FORCED_NP, + & spu, + static_cast< pthread_spu_t >( n), + PTHREAD_SELFTID_NP) ); + if ( errno_ != 0) + throw std::runtime_error("::pthread_processor_bind_np() failed"); +} + +#include <boost/config/abi_suffix.hpp> diff --git a/libs/context/performance/bind_processor_linux.cpp b/libs/context/performance/bind_processor_linux.cpp new file mode 100644 index 0000000000..3fb9588132 --- /dev/null +++ b/libs/context/performance/bind_processor_linux.cpp @@ -0,0 +1,30 @@ + +// 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) + +#include "bind_processor.hpp" + +extern "C" +{ +#include <pthread.h> +#include <sched.h> +} + +#include <stdexcept> + +#include <boost/config/abi_prefix.hpp> + +void bind_to_processor( unsigned int n) +{ + cpu_set_t cpuset; + CPU_ZERO( & cpuset); + CPU_SET( n, & cpuset); + + int errno_( ::pthread_setaffinity_np( ::pthread_self(), sizeof( cpuset), & cpuset) ); + if ( errno_ != 0) + throw std::runtime_error("::pthread_setaffinity_np() failed"); +} + +#include <boost/config/abi_suffix.hpp> diff --git a/libs/context/performance/bind_processor_solaris.cpp b/libs/context/performance/bind_processor_solaris.cpp new file mode 100644 index 0000000000..0830c1b453 --- /dev/null +++ b/libs/context/performance/bind_processor_solaris.cpp @@ -0,0 +1,26 @@ + +// 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) + +#include "bind_processor.hpp" + +extern "C" +{ +#include <sys/types.h> +#include <sys/processor.h> +#include <sys/procset.h> +} + +#include <stdexcept> + +#include <boost/config/abi_prefix.hpp> + +void bind_to_processor( unsigned int n) +{ + if ( ::processor_bind( P_LWPID, P_MYID, static_cast< processorid_t >( n), 0) == -1) + throw std::runtime_error("::processor_bind() failed"); +} + +#include <boost/config/abi_suffix.hpp> diff --git a/libs/context/performance/bind_processor_windows.cpp b/libs/context/performance/bind_processor_windows.cpp new file mode 100644 index 0000000000..6fefbc65f1 --- /dev/null +++ b/libs/context/performance/bind_processor_windows.cpp @@ -0,0 +1,24 @@ + +// 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) + +#include "bind_processor.hpp" + +extern "C" +{ +#include <windows.h> +} + +#include <stdexcept> + +#include <boost/config/abi_prefix.hpp> + +void bind_to_processor( unsigned int n) +{ + if ( ::SetThreadAffinityMask( ::GetCurrentThread(), ( DWORD_PTR)1 << n) == 0) + throw std::runtime_error("::SetThreadAffinityMask() failed"); +} + +#include <boost/config/abi_suffix.hpp> diff --git a/libs/context/performance/cycle.hpp b/libs/context/performance/cycle.hpp new file mode 100644 index 0000000000..c26c85983b --- /dev/null +++ b/libs/context/performance/cycle.hpp @@ -0,0 +1,26 @@ + +// 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 CYCLE_H +#define CYCLE_H + +// 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) +# include "cycle_x86-64.hpp" +// i386 +#elif defined(i386) || defined(__i386__) || defined(__i386) \ + || defined(__i486__) || defined(__i586__) || defined(__i686__) \ + || defined(__X86__) || defined(_X86_) || defined(__THW_INTEL__) \ + || defined(__I86__) || defined(__INTEL__) || defined(__IA32__) \ + || defined(_M_IX86) || defined(_I86_) +# include "cycle_i386.hpp" +#endif + +#endif // CYCLE_H diff --git a/libs/context/performance/cycle_i386.hpp b/libs/context/performance/cycle_i386.hpp new file mode 100644 index 0000000000..3e670077a1 --- /dev/null +++ b/libs/context/performance/cycle_i386.hpp @@ -0,0 +1,83 @@ + +// 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 CYCLE_I386_H +#define CYCLE_I386_H + +#include <algorithm> +#include <numeric> +#include <cstddef> +#include <vector> + +#include <boost/assert.hpp> +#include <boost/bind.hpp> +#include <boost/cstdint.hpp> + +#define BOOST_CONTEXT_CYCLE + +typedef boost::uint64_t cycle_t; + +#if _MSC_VER +inline +cycle_t cycles() +{ + cycle_t c; + __asm { + cpuid + rdtsc + mov dword ptr [c + 0], eax + mov dword ptr [c + 4], edx + } + return c; +} +#elif defined(__GNUC__) || \ + defined(__INTEL_COMPILER) || defined(__ICC) || defined(_ECC) || defined(__ICL) +inline +cycle_t cycles() +{ + boost::uint32_t lo, hi; + + __asm__ __volatile__ ( + "xorl %%eax, %%eax\n" + "cpuid\n" + ::: "%eax", "%ebx", "%ecx", "%edx" + ); + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi) ); + __asm__ __volatile__ ( + "xorl %%eax, %%eax\n" + "cpuid\n" + ::: "%eax", "%ebx", "%ecx", "%edx" + ); + + return ( cycle_t)hi << 32 | lo; +} +#else +# error "this compiler is not supported" +#endif + +struct measure_cycles +{ + cycle_t operator()() + { + cycle_t start( cycles() ); + return cycles() - start; + } +}; + +inline +cycle_t overhead_cycles() +{ + std::size_t iterations( 10); + std::vector< cycle_t > overhead( iterations, 0); + for ( std::size_t i( 0); i < iterations; ++i) + std::generate( + overhead.begin(), overhead.end(), + measure_cycles() ); + BOOST_ASSERT( overhead.begin() != overhead.end() ); + return std::accumulate( overhead.begin(), overhead.end(), 0) / iterations; +} + +#endif // CYCLE_I386_H diff --git a/libs/context/performance/cycle_x86-64.hpp b/libs/context/performance/cycle_x86-64.hpp new file mode 100644 index 0000000000..a2212b8120 --- /dev/null +++ b/libs/context/performance/cycle_x86-64.hpp @@ -0,0 +1,79 @@ + +// 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 CYCLE_X86_64_H +#define CYCLE_X86_64_H + +#include <algorithm> +#include <numeric> +#include <cstddef> +#include <vector> + +#include <boost/assert.hpp> +#include <boost/bind.hpp> +#include <boost/cstdint.hpp> + +#define BOOST_CONTEXT_CYCLE + +typedef boost::uint64_t cycle_t; + +#if _MSC_VER >= 1400 +# include <intrin.h> +# pragma intrinsic(__rdtsc) +inline +cycle_t cycles() +{ return __rdtsc(); } +#elif defined(__INTEL_COMPILER) || defined(__ICC) || defined(_ECC) || defined(__ICL) +inline +cycle_t cycles() +{ return __rdtsc(); } +#elif defined(__GNUC__) || defined(__SUNPRO_C) +inline +cycle_t cycles() +{ + boost::uint32_t lo, hi; + + __asm__ __volatile__ ( + "xorl %%eax, %%eax\n" + "cpuid\n" + ::: "%rax", "%rbx", "%rcx", "%rdx" + ); + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi) ); + __asm__ __volatile__ ( + "xorl %%eax, %%eax\n" + "cpuid\n" + ::: "%rax", "%rbx", "%rcx", "%rdx" + ); + + return ( cycle_t)hi << 32 | lo; +} +#else +# error "this compiler is not supported" +#endif + +struct measure_cycles +{ + cycle_t operator()() + { + cycle_t start( cycles() ); + return cycles() - start; + } +}; + +inline +cycle_t overhead_cycles() +{ + std::size_t iterations( 10); + std::vector< cycle_t > overhead( iterations, 0); + for ( std::size_t i( 0); i < iterations; ++i) + std::generate( + overhead.begin(), overhead.end(), + measure_cycles() ); + BOOST_ASSERT( overhead.begin() != overhead.end() ); + return std::accumulate( overhead.begin(), overhead.end(), 0) / iterations; +} + +#endif // CYCLE_X86_64_H diff --git a/libs/context/performance/performance.cpp b/libs/context/performance/performance.cpp new file mode 100644 index 0000000000..f6461e1fb0 --- /dev/null +++ b/libs/context/performance/performance.cpp @@ -0,0 +1,262 @@ + +// 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_PP_LIMIT_MAG 10 + +#include <cstdio> +#include <cstdlib> +#include <iostream> +#include <stdexcept> + +#include <boost/assert.hpp> +#include <boost/bind.hpp> +#include <boost/function.hpp> +#include <boost/config.hpp> +#include <boost/context/all.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/program_options.hpp> + +#ifndef BOOST_WINDOWS +#include <ucontext.h> +#endif + +#include "bind_processor.hpp" +#include "cycle.hpp" + +#if _POSIX_C_SOURCE >= 199309L +#include "zeit.hpp" +#endif + +namespace ctx = boost::ctx; + +bool preserve_fpu = false; + +#define CALL_FUNCTION(z,n,unused) \ + fn(); + +#define CALL_UCONTEXT(z,n,unused) \ + ::swapcontext( & ucm, & uc); + +#define CALL_FCONTEXT(z,n,unused) \ + ctx::jump_fcontext( & fcm, & fc, 7, preserve_fpu); + +#ifndef BOOST_WINDOWS +ucontext_t uc, ucm; +#endif +ctx::fcontext_t fc, fcm; + +static void f3() +{ } + +#ifndef BOOST_WINDOWS +static void f2() +{ + while ( true) + ::swapcontext( & uc, & ucm); +} +#endif + +static void f1( intptr_t) +{ + while ( true) + ctx::jump_fcontext( & fc, & fcm, 7, preserve_fpu); +} + +#ifdef BOOST_CONTEXT_CYCLE +cycle_t test_function_cycle( cycle_t ov) +{ + boost::function< void() > fn( boost::bind( f3) ); + // cache warum-up +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_FUNCTION, ~) + cycle_t total( cycles() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} + +#ifndef BOOST_WINDOWS +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_size = ctx::default_stacksize(); + ::makecontext( & uc, f2, 7); + + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + + cycle_t start( cycles() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + cycle_t total( cycles() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +#endif + +cycle_t test_fcontext_cycle( cycle_t ov) +{ + ctx::stack_allocator alloc; + fc.fc_stack.base = alloc.allocate(ctx::default_stacksize()); + fc.fc_stack.limit = + static_cast< char * >( fc.fc_stack.base) - ctx::default_stacksize(); + ctx::make_fcontext( & fc, f1); + + ctx::jump_fcontext( & fcm, & fc, 7, preserve_fpu); + + // cache warum-up +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_FCONTEXT, ~) + cycle_t total( cycles() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +#endif + +#if _POSIX_C_SOURCE >= 199309L +zeit_t test_function_zeit( zeit_t ov) +{ + boost::function< void() > fn( boost::bind( f3) ); + // cache warum-up +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_FUNCTION, ~) + zeit_t total( zeit() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} + +#ifndef BOOST_WINDOWS +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_size = ctx::default_stacksize(); + ::makecontext( & uc, f2, 7); + + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + + zeit_t start( zeit() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + zeit_t total( zeit() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +#endif + +zeit_t test_fcontext_zeit( zeit_t ov) +{ + ctx::stack_allocator alloc; + fc.fc_stack.base = alloc.allocate(ctx::default_stacksize()); + fc.fc_stack.limit = + static_cast< char * >( fc.fc_stack.base) - ctx::default_stacksize(); + ctx::make_fcontext( & fc, f1); + + ctx::jump_fcontext( & fcm, & fc, 7, preserve_fpu); + + // cache warum-up +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_FCONTEXT, ~) + zeit_t total( zeit() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +#endif + +int main( int argc, char * argv[]) +{ + try + { + bind_to_processor( 0); + +#ifdef BOOST_CONTEXT_CYCLE + { + cycle_t ov( overhead_cycles() ); + std::cout << "overhead for rdtsc == " << ov << " cycles" << std::endl; + + unsigned int res = test_fcontext_cycle( ov); + std::cout << "fcontext: average of " << res << " cycles per switch" << std::endl; +#ifndef BOOST_WINDOWS + res = test_ucontext_cycle( ov); + std::cout << "ucontext: average of " << res << " cycles per switch" << std::endl; +#endif + res = test_function_cycle( ov); + std::cout << "boost::function: average of " << res << " cycles per switch" << std::endl; + } +#endif + +#if _POSIX_C_SOURCE >= 199309L + { + zeit_t ov( overhead_zeit() ); + std::cout << "\noverhead for clock_gettime() == " << ov << " ns" << std::endl; + + unsigned int res = test_fcontext_zeit( ov); + std::cout << "fcontext: average of " << res << " ns per switch" << std::endl; +#ifndef BOOST_WINDOWS + res = test_ucontext_zeit( ov); + std::cout << "ucontext: average of " << res << " ns per switch" << std::endl; +#endif + res = test_function_zeit( ov); + std::cout << "boost::function: average of " << res << " ns per switch" << std::endl; + } +#endif + + return EXIT_SUCCESS; + } + catch ( std::exception const& e) + { std::cerr << "exception: " << e.what() << std::endl; } + catch (...) + { std::cerr << "unhandled exception" << std::endl; } + return EXIT_FAILURE; +} + +#undef CALL_FCONTEXT +#undef CALL_UCONTEXT diff --git a/libs/context/performance/zeit.hpp b/libs/context/performance/zeit.hpp new file mode 100644 index 0000000000..2c082bf220 --- /dev/null +++ b/libs/context/performance/zeit.hpp @@ -0,0 +1,53 @@ + +// 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 ZEIT_H +#define ZEIT_H + +#include <time.h> + +#include <algorithm> +#include <numeric> +#include <cstddef> +#include <vector> + +#include <boost/assert.hpp> +#include <boost/bind.hpp> +#include <boost/cstdint.hpp> + +typedef boost::uint64_t zeit_t; + +inline +zeit_t zeit() +{ + timespec t; + ::clock_gettime( CLOCK_PROCESS_CPUTIME_ID, & t); + return t.tv_sec * 1000000000 + t.tv_nsec; +} + +struct measure_zeit +{ + zeit_t operator()() + { + zeit_t start( zeit() ); + return zeit() - start; + } +}; + +inline +zeit_t overhead_zeit() +{ + std::size_t iterations( 10); + std::vector< zeit_t > overhead( iterations, 0); + for ( std::size_t i( 0); i < iterations; ++i) + std::generate( + overhead.begin(), overhead.end(), + measure_zeit() ); + BOOST_ASSERT( overhead.begin() != overhead.end() ); + return std::accumulate( overhead.begin(), overhead.end(), 0) / iterations; +} + +#endif // ZEIT_H diff --git a/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S b/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S new file mode 100644 index 0000000000..7724441c5b --- /dev/null +++ b/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S @@ -0,0 +1,101 @@ +/* + 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) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| 0x20| 0x24| * + * ------------------------------------------------------------- * + * | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | sp | lr | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | | * + * ------------------------------------------------------------- * + * | 0x28| | * + * ------------------------------------------------------------- * + * | pc | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 11 | 12 | | * + * ------------------------------------------------------------- * + * | 0x2c| 0x30| | * + * ------------------------------------------------------------- * + * |sbase|slimit| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | * + * ------------------------------------------------------------- * + * | 0x34| 0x38|0x3c| 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58 | * + * ------------------------------------------------------------- * + * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | s24 | s25 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 23 | 24 | 25 | 26 | 27 | 28 | | * + * ------------------------------------------------------------- * + * | 0x5c| 0x60| 0x64| 0x68| 0x6c| 0x70| | * + * ------------------------------------------------------------- * + * | s26 | s27 | s28 | s29 | s30 | s31 | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,%function +jump_fcontext: + stmia a1, {v1-v8,sp-lr} @ save V1-V8,SP-LR + str lr, [a1,#40] @ save LR as PC + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) + cmp a4, #0 @ test if fpu env should be preserved + beq 1f + + mov a4, a1 + add a4, #52 + fstmiax a4, {d8-d15} @ save S16-S31 + + mov a4, a2 + add a4, #52 + fldmiax a4, {d8-d15} @ restore S16-S31 +1: +#endif + + mov a1, a3 @ use third arg as return value after jump + @ and as first arg in context function + ldmia a2, {v1-v8,sp-pc} @ restore v1-V8,SP-PC +.size jump_fcontext,.-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,%function +make_fcontext: + str a1, [a1,#0] @ save the address of passed context + str a2, [a1,#40] @ save address of the context function + ldr a2, [a1,#44] @ load the stack base + + push {a1,lr} @ save pointer to fcontext_t + mov a1, a2 @ stack pointer as arg for align_stack + bl align_stack@PLT @ align stack + mov a2, a1 @ begin of aligned stack + pop {a1,lr} @ restore pointer to fcontext_t + + str a2, [a1,#32] @ save the aligned stack base + + adr a2, finish @ address of finish; called after context function returns + str a2, [a1,#36] + + mov a1, #0 + bx lr + +finish: + mov a1, #0 @ exit code is zero + bl _exit@PLT @ exit application +.size make_fcontext,.-make_fcontext diff --git a/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm b/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm new file mode 100644 index 0000000000..0f4dd671b1 --- /dev/null +++ b/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm @@ -0,0 +1,151 @@ + +; 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) + +; -------------------------------------------------------------- +; | 0 | 1 | 2 | 3 | 4 | 5 | +; -------------------------------------------------------------- +; | 0h | 04h | 08h | 0ch | 010h | 014h | +; -------------------------------------------------------------- +; | EDI | ESI | EBX | EBP | ESP | EIP | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 6 | 7 | | +; -------------------------------------------------------------- +; | 018h | 01ch | | +; -------------------------------------------------------------- +; | ss_base | ss_limit| | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 8 | | +; -------------------------------------------------------------- +; | 020h | | +; -------------------------------------------------------------- +; |fc_execpt| | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 9 | | +; -------------------------------------------------------------- +; | 024h | | +; -------------------------------------------------------------- +; |fc_strage| | +; -------------------------------------------------------------- +; -------------------------------------------------------------- +; | 10 | 11 | | +; -------------------------------------------------------------- +; | 028h | 02ch | | +; -------------------------------------------------------------- +; | fc_mxcsr|fc_x87_cw| | +; -------------------------------------------------------------- + +.386 +.XMM +.model flat, c +_exit PROTO, value:SDWORD +align_stack PROTO, vp:DWORD +seh_fcontext PROTO, except:DWORD, frame:DWORD, context:DWORD, dispatch:DWORD +.code + +jump_fcontext PROC EXPORT + mov ecx, [esp+04h] ; load address of the first fcontext_t arg + mov [ecx], edi ; save EDI + mov [ecx+04h], esi ; save ESI + mov [ecx+08h], ebx ; save EBX + mov [ecx+0ch], ebp ; save EBP + + assume fs:nothing + mov edx, fs:[018h] ; load NT_TIB + assume fs:error + mov eax, [edx] ; load current SEH exception list + mov [ecx+020h], eax ; save current exception list + mov eax, [edx+04h] ; load current stack base + mov [ecx+018h], eax ; save current stack base + mov eax, [edx+08h] ; load current stack limit + mov [ecx+01ch], eax ; save current stack limit + mov eax, [edx+010h] ; load fiber local storage + mov [ecx+024h], eax ; save fiber local storage + + lea eax, [esp+04h] ; exclude the return address + mov [ecx+010h], eax ; save as stack pointer + mov eax, [esp] ; load return address + mov [ecx+014h], eax ; save return address + + mov edx, [esp+08h] ; load address of the second fcontext_t arg + mov edi, [edx] ; restore EDI + mov esi, [edx+04h] ; restore ESI + mov ebx, [edx+08h] ; restore EBX + mov ebp, [edx+0ch] ; restore EBP + + mov eax, [esp+010h] ; check if fpu enve preserving was requested + test eax, eax + je nxt + + stmxcsr [ecx+028h] ; save MMX control word + fnstcw [ecx+02ch] ; save x87 control word + ldmxcsr [edx+028h] ; restore MMX control word + fldcw [edx+02ch] ; restore x87 control word +nxt: + mov ecx, edx + assume fs:nothing + mov edx, fs:[018h] ; load NT_TIB + assume fs:error + mov eax, [ecx+020h] ; load SEH exception list + mov [edx], eax ; restore next SEH item + mov eax, [ecx+018h] ; load stack base + mov [edx+04h], eax ; restore stack base + mov eax, [ecx+01ch] ; load stack limit + mov [edx+08h], eax ; restore stack limit + mov eax, [ecx+024h] ; load fiber local storage + mov [edx+010h], eax ; restore fiber local storage + + mov eax, [esp+0ch] ; use third arg as return value after jump + + mov esp, [ecx+010h] ; restore ESP + mov [esp+04h], eax ; use third arg as first arg in context function + mov ecx, [ecx+014h] ; fetch the address to return to + + jmp ecx ; indirect jump to context +jump_fcontext ENDP + +make_fcontext PROC EXPORT + mov eax, [esp+04h] ; load address of the fcontext_t arg0 + mov [eax], eax ; save the address of passed context + mov ecx, [esp+08h] ; load the address of the context function + mov [eax+014h], ecx ; save the address of the context function + mov edx, [eax+018h] ; load the stack base + + push eax ; save pointer to fcontext_t + push edx ; stack pointer as arg for align_stack + call align_stack ; align stack + mov edx, eax ; begin of aligned stack + pop eax ; remove arg for align_stack + pop eax ; restore pointer to fcontext_t + + lea edx, [edx-014h] ; reserve space for last frame on stack, (ESP + 4) & 15 == 0 + mov [eax+010h], edx ; save the aligned stack + + mov ecx, seh_fcontext ; set ECX to exception-handler + mov [edx+0ch], 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 [eax+02ch], ecx ; save next SEH + + stmxcsr [eax+028h] ; save MMX control word + fnstcw [eax+02ch] ; save x87 control word + + mov ecx, finish ; address of finish + mov [edx], ecx + + xor eax, eax + ret + +finish: + xor eax, eax + push eax ; exit code is zero + call _exit ; exit application + hlt +make_fcontext ENDP +END diff --git a/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S b/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S new file mode 100644 index 0000000000..7c94ea068d --- /dev/null +++ b/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S @@ -0,0 +1,122 @@ +/* + 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) +*/ + +/******************************************************************** + * * + * -------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | * + * -------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | * + * -------------------------------------------------------------- * + * | EDI | ESI | EBX | EBP | ESP | EIP | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 6 | 7 | | * + * -------------------------------------------------------------- * + * | 0x18 | 0x1c | | * + * -------------------------------------------------------------- * + * | sbase | slimit | | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 8 | 9 | | * + * -------------------------------------------------------------- * + * | 0x20 | 0x24 | | * + * -------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * -------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,@function +jump_fcontext: + movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */ + movl %edi, (%ecx) /* save EDI */ + movl %esi, 0x4(%ecx) /* save ESI */ + movl %ebx, 0x8(%ecx) /* save EBX */ + movl %ebp, 0xc(%ecx) /* save EBP */ + + leal 0x4(%esp), %eax /* exclude the return address */ + movl %eax, 0x10(%ecx) /* save as stack pointer */ + movl (%esp), %eax /* load return address */ + movl %eax, 0x14(%ecx) /* save return address */ + + movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */ + movl (%edx), %edi /* restore EDI */ + movl 0x4(%edx), %esi /* restore ESI */ + movl 0x8(%edx), %ebx /* restore EBX */ + movl 0xc(%edx), %ebp /* restore EBP */ + + movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */ + test %eax, %eax + je 1f + + stmxcsr 0x20(%ecx) /* save MMX control and status word */ + fnstcw 0x24(%ecx) /* save x87 control word */ + ldmxcsr 0x20(%edx) /* restore MMX control and status word */ + fldcw 0x24(%edx) /* restore x87 control word */ +1: + movl 0xc(%esp), %eax /* use third arg as return value after jump */ + + movl 0x10(%edx), %esp /* restore ESP */ + movl %eax, 0x4(%esp) /* use third arg as first arg in context function */ + movl 0x14(%edx), %edx /* fetch the address to return to */ + + jmp *%edx /* indirect jump to context */ +.size jump_fcontext,.-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,@function +make_fcontext: + movl 0x4(%esp), %eax /* load address of the fcontext_t */ + movl %eax, (%eax) /* save the address of current context */ + movl 0x8(%esp), %ecx /* load the address of the context function */ + movl %ecx, 0x14(%eax) /* save the address of the context function */ + movl 0x18(%eax), %edx /* load the stack base */ + + pushl %eax /* save pointer to fcontext_t */ + pushl %ebx /* save EBX */ + pushl %edx /* 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@PLT /* align stack */ + movl %eax, %edx /* begin of aligned 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 stack, (ESP + 4) % 16 == 0 */ + movl %edx, 0x10(%eax) /* save the aligned stack base */ + + 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) + + xorl %eax, %eax + ret + +finish: + leal -0xc(%esp), %esp + + 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 */ + call _exit@PLT /* exit application */ + hlt +.size make_fcontext,.-make_fcontext diff --git a/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S b/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S new file mode 100644 index 0000000000..a28c87576a --- /dev/null +++ b/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S @@ -0,0 +1,118 @@ +/* + 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) +*/ + +/******************************************************************** + * * + * -------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | * + * -------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | * + * -------------------------------------------------------------- * + * | EDI | ESI | EBX | EBP | ESP | EIP | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 6 | 7 | | * + * -------------------------------------------------------------- * + * | 0x18 | 0x1c | | * + * -------------------------------------------------------------- * + * | sbase | slimit | | * + * -------------------------------------------------------------- * + * -------------------------------------------------------------- * + * | 8 | 9 | | * + * -------------------------------------------------------------- * + * | 0x20 | 0x24 | | * + * -------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * -------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl _jump_fcontext +.align 2 +_jump_fcontext: + movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */ + movl %edi, (%ecx) /* save EDI */ + movl %esi, 0x4(%ecx) /* save ESI */ + movl %ebx, 0x8(%ecx) /* save EBX */ + movl %ebp, 0xc(%ecx) /* save EBP */ + + leal 0x4(%esp), %eax /* exclude the return address */ + movl %eax, 0x10(%ecx) /* save as stack pointer */ + movl (%esp), %eax /* load return address */ + movl %eax, 0x14(%ecx) /* save return address */ + + movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */ + movl (%edx), %edi /* restore EDI */ + movl 0x4(%edx), %esi /* restore ESI */ + movl 0x8(%edx), %ebx /* restore EBX */ + movl 0xc(%edx), %ebp /* restore EBP */ + + movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */ + test %eax, %eax + je 1f + + stmxcsr 0x20(%ecx) /* save MMX control and status word */ + fnstcw 0x24(%ecx) /* save x87 control word */ + ldmxcsr 0x20(%edx) /* restore MMX control and status word */ + fldcw 0x24(%edx) /* restore x87 control word */ +1: + movl 0xc(%esp), %eax /* use third arg as return value after jump */ + + movl 0x10(%edx), %esp /* restore ESP */ + movl %eax, 0x4(%esp) /* use third arg as first arg in context function */ + movl 0x14(%edx), %edx /* fetch the address to return to */ + + jmp *%edx /* indirect jump to context */ + +.text +.globl _make_fcontext +.align 2 +_make_fcontext: + movl 0x4(%esp), %eax /* load address of the fcontext_t */ + movl %eax, (%eax) /* save the address of current context */ + movl 0x8(%esp), %ecx /* load the address of the context function */ + movl %ecx, 0x14(%eax) /* save the address of the context function */ + movl 0x18(%eax), %edx /* load the stack base */ + + pushl %eax /* save pointer to fcontext_t */ + pushl %ebx /* save EBX */ + pushl %edx /* 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@PLT /* align stack */ + movl %eax, %edx /* begin of aligned 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 stack, (ESP + 4) % 16 == 0 */ + movl %edx, 0x10(%eax) /* save the aligned stack base */ + + 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) + + xorl %eax, %eax + ret + +finish: + leal -0xc(%esp), %esp + + 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 */ + call _exit@PLT /* exit application */ + hlt diff --git a/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S b/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S new file mode 100644 index 0000000000..be86f185ec --- /dev/null +++ b/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S @@ -0,0 +1,144 @@ +/* + 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) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 | * + * ------------------------------------------------------------- * + * | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | GP | SP | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | 11 | 12 | | * + * ------------------------------------------------------------- * + * | 80 | 88 | 96 | | * + * ------------------------------------------------------------- * + * | S8 | RA | PC | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 13 | 14 | | * + * ------------------------------------------------------------- * + * | 104 | 112 | | * + * ------------------------------------------------------------- * + * |sbase|slimt| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 15 | 16 | 17 | 18 | 19 | 20 | | * + * ------------------------------------------------------------- * + * | 120 | 128 | 136 | 144 | 152 | 160 | | * + * ------------------------------------------------------------- * + * | F20 | F22 | F24 | F26 | F28 | F30 | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,@function +.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 + +#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 +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 + + 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 + jr $t9 # jump to context +.end jump_fcontext +.size jump_fcontext, .-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,@function +.ent make_fcontext +make_fcontext: +#ifdef __PIC__ +.set noreorder +.cpload $t9 +.set reorder +#endif + sw $a0, ($a0) # save the current context + sw $gp, 24($a0) # save global pointer + sw $a1, 96($a0) # save the address of the context function + lw $t0, 104($a0) # load the stack base + + sub $sp, $sp, 28 + sw $ra, 24($sp) + sw $a0, 20($sp) + move $a0, $t0 # stack pointer as arg for align_stack + lw $t9, %call16(align_stack)($gp) # align stack + jalr $t9 + nop + move $t0, $v0 # begin of aligned stack + lw $ra, 24($sp) + lw $a0, 20($sp) + addi $sp, $sp, 28 + + sub $t0, $t0, 16 # reserve 16 byte of argument space + sw $t0, 72($a0) # save the algned stack base + + la $t9, finish # helper code executed after context function returns + sw $t9, 88($a0) + + move $v0, $zero + jr $ra + +finish: + move $gp, $s3 # restore GP (global pointer) + move $a0, $zero # exit code is zero + lw $t9, %call16(_exit)($gp) # exit application + jalr $t9 +.end make_fcontext +.size make_fcontext, .-make_fcontext diff --git a/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S b/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S new file mode 100644 index 0000000000..69b6ed90b5 --- /dev/null +++ b/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S @@ -0,0 +1,222 @@ +/* + 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) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | * + * ------------------------------------------------------------- * + * | R13 | R14 | R15 | R16 | R17 | R18 | R19 | R20 | R21 | R22 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | * + * ------------------------------------------------------------- * + * | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | * + * ------------------------------------------------------------- * + * | R23 | R24 | R25 | R26 | R27 | R28 | R29 | R30 | R31 | SP | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 20 | 21 | 22 | | * + * ------------------------------------------------------------- * + * | 80 | 84 | 88 | | * + * ------------------------------------------------------------- * + * | CR | LR | PC | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 23 | 24 | | * + * ------------------------------------------------------------- * + * | 92 | 96 | | * + * ------------------------------------------------------------- * + * |sbase|slimt| | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | * + * ------------------------------------------------------------- * + * | 100 | 104 | 108 | 112 | 116 | 120 | 124 | 128 | 132 | 136 | * + * ------------------------------------------------------------- * + * | F14 | F15 | F16 | F17 | F18 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | * + * ------------------------------------------------------------- * + * | 140 | 144 | 148 | 152 | 156 | 160 | 164 | 168 | 172 | 176 | * + * ------------------------------------------------------------- * + * | F19 | F20 | F21 | F22 | F23 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | * + * ------------------------------------------------------------- * + * | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 208 | 212 | 216 | * + * ------------------------------------------------------------- * + * | F24 | F25 | F26 | F27 | F28 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | | * + * ------------------------------------------------------------- * + * | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | | * + * ------------------------------------------------------------- * + * | F29 | F30 | F31 | fpscr | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.text +.globl jump_fcontext +.align 2 +.type jump_fcontext,@function +jump_fcontext: + stw %r13, 0(%r3) # save R13 + stw %r14, 4(%r3) # save R14 + stw %r15, 8(%r3) # save R15 + stw %r16, 12(%r3) # save R16 + stw %r17, 16(%r3) # save R17 + stw %r18, 20(%r3) # save R18 + stw %r19, 24(%r3) # save R19 + stw %r20, 28(%r3) # save R20 + stw %r21, 32(%r3) # save R21 + stw %r22, 36(%r3) # save R22 + stw %r23, 40(%r3) # save R23 + stw %r24, 44(%r3) # save R24 + stw %r25, 48(%r3) # save R25 + stw %r26, 52(%r3) # save R26 + stw %r27, 56(%r3) # save R27 + stw %r28, 60(%r3) # save R28 + stw %r29, 64(%r3) # save R29 + stw %r30, 68(%r3) # save R30 + stw %r31, 72(%r3) # save R31 + stw %r1, 76(%r3) # save SP + + mfcr %r0 # load CR + stw %r0, 80(%r3) # save CR + mflr %r0 # load LR + stw %r0, 84(%r3) # save LR + stw %r0, 88(%r3) # save LR as PC + + cmpwi cr7, %r6, 0 # test if fpu env should be preserved + beq cr7, 1f + + stfd %f14, 100(%r3) # save F14 + stfd %f15, 108(%r3) # save F15 + stfd %f16, 116(%r3) # save F16 + stfd %f17, 124(%r3) # save F17 + stfd %f18, 132(%r3) # save F18 + stfd %f19, 140(%r3) # save F19 + stfd %f20, 148(%r3) # save F20 + stfd %f21, 156(%r3) # save F21 + stfd %f22, 164(%r3) # save F22 + stfd %f23, 172(%r3) # save F23 + stfd %f24, 180(%r3) # save F24 + stfd %f25, 188(%r3) # save F25 + stfd %f26, 196(%r3) # save F26 + stfd %f27, 204(%r3) # save F27 + stfd %f28, 212(%r3) # save F28 + stfd %f29, 220(%r3) # save F29 + stfd %f30, 228(%r3) # save F30 + stfd %f31, 236(%r3) # save F31 + mffs %f0 # load FPSCR + stfd %f0, 244(%r3) # save FPSCR + + lfd %f14, 100(%r4) # restore F14 + lfd %f15, 108(%r4) # restore F15 + lfd %f16, 116(%r4) # restore F16 + lfd %f17, 124(%r4) # restore F17 + lfd %f18, 132(%r4) # restore F18 + lfd %f19, 140(%r4) # restore F19 + lfd %f20, 148(%r4) # restore F20 + lfd %f21, 156(%r4) # restore F21 + lfd %f22, 164(%r4) # restore F22 + lfd %f23, 172(%r4) # restore F23 + lfd %f24, 180(%r4) # restore F24 + lfd %f25, 188(%r4) # restore F25 + lfd %f26, 196(%r4) # restore F26 + lfd %f27, 204(%r4) # restore F27 + lfd %f28, 212(%r4) # restore F28 + lfd %f29, 220(%r4) # restore F29 + lfd %f30, 228(%r4) # restore F30 + lfd %f31, 236(%r4) # restore F31 + lfd %f0, 244(%r4) # load FPSCR + mtfsf 0xff, %f0 # restore FPSCR +1: + + lwz %r13, 0(%r4) # restore R13 + lwz %r14, 4(%r4) # restore R14 + lwz %r15, 8(%r4) # restore R15 + lwz %r16, 12(%r4) # restore R16 + lwz %r17, 16(%r4) # restore R17 + lwz %r18, 20(%r4) # restore R18 + lwz %r19, 24(%r4) # restore R19 + lwz %r20, 28(%r4) # restore R20 + lwz %r21, 32(%r4) # restore R21 + lwz %r22, 36(%r4) # restore R22 + lwz %r23, 40(%r4) # restore R23 + lwz %r24, 44(%r4) # restore R24 + lwz %r25, 48(%r4) # restore R25 + lwz %r26, 52(%r4) # restore R26 + lwz %r27, 56(%r4) # restore R27 + lwz %r28, 60(%r4) # restore R28 + lwz %r29, 64(%r4) # restore R29 + lwz %r30, 68(%r4) # restore R30 + lwz %r31, 72(%r4) # restore R31 + lwz %r1, 76(%r4) # restore SP + + lwz %r0, 80(%r4) # load CR + mtcr %r0 # restore CR + lwz %r0, 84(%r4) # load LR + mtlr %r0 # restore LR + + mr. %r3, %r5 # use third arg as return value after jump + # and as first arg in context function + + lwz %r0, 88(%r4) # load PC + mtctr %r0 # restore CTR + + bctr # jump to context +.size jump_fcontext, .-jump_fcontext + +.text +.globl make_fcontext +.align 2 +.type make_fcontext,@function +make_fcontext: + stw %r3, 0(%r3) # save the current context + stw %r4, 88(%r3) # save the address of the context function + lwz %r0, 92(%r3) # load the stack base + + li %r4, 28 + subf %r1, %r4, %r1 # reserve space on stack + stw %r3, 24(%r1) # store pointer to fcontext_t on stack + mflr %r4 # load LR + stw %r4, 20(%r1) # store LR on stack + mr. %r3, %r0 # context stack as arg to align_stack + bl align_stack@plt # call align_stack + mr. %r0, %r3 # load result into R0 + lwz %r4, 20(%r1) # pop LR from stack + mtlr %r4 # restore LR + lwz %r3, 24(%r1) # pop pointer to fcontext_t from stack + addi %r1, %r1, 28 # release space on stack + + li %r4, 32 + subf %r0, %r4, %r0 # 32 bytes on stack for parameter area(== 8 registers) + stw %r0, 76(%r3) # save the aligned stack base + + mflr %r0 # load LR + bl 1f # jump to label 1 +1: + mflr %r4 # load LR + addi %r4, %r4, finish - 1b # address of finish; called after context function returns + mtlr %r0 # restore LR + stw %r4, 84(%r3) + + li %r3, 0 + blr + +finish: + li %r3, 0 # exit code is zero + bl _exit@plt # exit application +.size make_fcontext, .-make_fcontext diff --git a/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S b/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S new file mode 100644 index 0000000000..0fcb387355 --- /dev/null +++ b/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S @@ -0,0 +1,250 @@ +/* + 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) +*/ + +/******************************************************************* + * * + * ------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * + * ------------------------------------------------------------- * + * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | * + * ------------------------------------------------------------- * + * | R13 | R14 | R15 | R16 | R17 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | * + * ------------------------------------------------------------- * + * | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | * + * ------------------------------------------------------------- * + * | R18 | R19 | R20 | R21 | R22 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | * + * ------------------------------------------------------------- * + * | 80 | 84 | 88 | 92 | 96 | 100 | 104 | 108 | 112 | 116 | * + * ------------------------------------------------------------- * + * | R23 | R24 | R25 | R26 | R27 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------------------- * + * | 120 | 124 | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | * + * ------------------------------------------------------------- * + * | R28 | R29 | R30 | R31 | SP | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 40 | 41 | 42 | 43 | 44 | 45 | | * + * ------------------------------------------------------------- * + * | 160 | 164 | 168 | 172 | 176 | 180 | | * + * ------------------------------------------------------------- * + * | CR | LR | PC | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 46 | 47 | 48 | 49 | | * + * ------------------------------------------------------------- * + * | 184 | 188 | 192 | 196 | | * + * ------------------------------------------------------------- * + * | sbase | slimt | | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | * + * ------------------------------------------------------------- * + * | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | * + * ------------------------------------------------------------- * + * | F14 | F15 | F16 | F17 | F18 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | * + * ------------------------------------------------------------- * + * | 240 | 244 | 248 | 252 | 256 | 260 | 264 | 268 | 272 | 276 | * + * ------------------------------------------------------------- * + * | F19 | F20 | F21 | F22 | F23 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | * + * ------------------------------------------------------------- * + * | 280 | 284 | 288 | 292 | 296 | 300 | 304 | 308 | 312 | 316 | * + * ------------------------------------------------------------- * + * | F24 | F25 | F26 | F27 | F28 | * + * ------------------------------------------------------------- * + * ------------------------------------------------------------- * + * | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | | * + * ------------------------------------------------------------- * + * | 320 | 324 | 328 | 332 | 336 | 340 | 344 | 348 | | * + * ------------------------------------------------------------- * + * | F29 | F30 | F31 | fpscr | | * + * ------------------------------------------------------------- * + * * + * *****************************************************************/ + +.section ".text" +.align 2 +.globl jump_fcontext +.section ".opd","aw" +.align 3 +jump_fcontext: +.quad .jump_fcontext,.TOC.@tocbase,0 +.previous +.size jump_fcontext,24 +.type .jump_fcontext,@function +.globl .jump_fcontext +.jump_fcontext: + std %r13, 0(%r3) # save R13 + std %r14, 8(%r3) # save R14 + std %r15, 16(%r3) # save R15 + std %r16, 24(%r3) # save R16 + std %r17, 32(%r3) # save R17 + std %r18, 40(%r3) # save R18 + std %r19, 48(%r3) # save R19 + std %r20, 56(%r3) # save R20 + std %r21, 64(%r3) # save R21 + std %r22, 72(%r3) # save R22 + std %r23, 80(%r3) # save R23 + std %r24, 88(%r3) # save R24 + std %r25, 96(%r3) # save R25 + std %r26, 104(%r3) # save R26 + std %r27, 112(%r3) # save R27 + std %r28, 120(%r3) # save R28 + std %r29, 128(%r3) # save R29 + std %r30, 136(%r3) # save R30 + std %r31, 144(%r3) # save R31 + std %r1, 152(%r3) # save SP + + mfcr %r0 # load CR + std %r0, 160(%r3) # save CR + mflr %r0 # load LR + std %r0, 168(%r3) # save LR + std %r0, 176(%r3) # save LR as PC + + cmpwi cr7, %r6, 0 # test if fpu env should be preserved + beq cr7, 1f + + stfd %f14, 200(%r3) # save F14 + stfd %f15, 208(%r3) # save F15 + stfd %f16, 216(%r3) # save F16 + stfd %f17, 224(%r3) # save F17 + stfd %f18, 232(%r3) # save F18 + stfd %f19, 240(%r3) # save F19 + stfd %f20, 248(%r3) # save F20 + stfd %f21, 256(%r3) # save F21 + stfd %f22, 264(%r3) # save F22 + stfd %f23, 272(%r3) # save F23 + stfd %f24, 280(%r3) # save F24 + stfd %f25, 288(%r3) # save F25 + stfd %f26, 296(%r3) # save F26 + stfd %f27, 304(%r3) # save F27 + stfd %f28, 312(%r3) # save F28 + stfd %f29, 320(%r3) # save F29 + stfd %f30, 328(%r3) # save F30 + stfd %f31, 336(%r3) # save F31 + mffs %f0 # load FPSCR + stfd %f0, 344(%r3) # save FPSCR + + lfd %f14, 200(%r4) # restore F14 + lfd %f15, 208(%r4) # restore F15 + lfd %f16, 216(%r4) # restore F16 + lfd %f17, 224(%r4) # restore F17 + lfd %f18, 232(%r4) # restore F18 + lfd %f19, 240(%r4) # restore F19 + lfd %f20, 248(%r4) # restore F20 + lfd %f21, 256(%r4) # restore F21 + lfd %f22, 264(%r4) # restore F22 + lfd %f23, 272(%r4) # restore F23 + lfd %f24, 280(%r4) # restore F24 + lfd %f25, 288(%r4) # restore F25 + lfd %f26, 296(%r4) # restore F26 + lfd %f27, 304(%r4) # restore F27 + lfd %f28, 312(%r4) # restore F28 + lfd %f29, 320(%r4) # restore F29 + lfd %f30, 328(%r4) # restore F30 + lfd %f31, 336(%r4) # restore F31 + lfd %f0, 344(%r4) # load FPSCR + mtfsf 0xff, %f0 # restore FPSCR +1: + + ld %r13, 0(%r4) # restore R13 + ld %r14, 8(%r4) # restore R14 + ld %r15, 16(%r4) # restore R15 + ld %r16, 24(%r4) # restore R16 + ld %r17, 32(%r4) # restore R17 + ld %r18, 40(%r4) # restore R18 + ld %r19, 48(%r4) # restore R19 + ld %r20, 56(%r4) # restore R20 + ld %r21, 64(%r4) # restore R21 + ld %r22, 72(%r4) # restore R22 + ld %r23, 80(%r4) # restore R23 + ld %r24, 88(%r4) # restore R24 + ld %r25, 96(%r4) # restore R25 + ld %r26, 104(%r4) # restore R26 + ld %r27, 112(%r4) # restore R27 + ld %r28, 120(%r4) # restore R28 + ld %r29, 128(%r4) # restore R29 + ld %r30, 136(%r4) # restore r30 + ld %r31, 144(%r4) # restore r31 + ld %r1, 152(%r4) # restore SP + + ld %r0, 160(%r4) # load CR + mtcr %r0 # restore CR + ld %r0, 168(%r4) # load LR + mtlr %r0 # restore LR + + mr. %r3, %r5 # use third arg as return value after jump + # and as first arg in context function + + ld %r0, 176(%r4) # load PC + mtctr %r0 # restore CTR + + bctr # jump to context +.size .jump_fcontext, .-.jump_fcontext + +.section ".text" +.align 2 +.globl make_fcontext +.section ".opd","aw" +.align 3 +make_fcontext: +.quad .make_fcontext,.TOC.@tocbase,0 +.previous +.size make_fcontext,24 +.type .make_fcontext,@function +.globl .make_fcontext +.make_fcontext: + std %r3, 0(%r3) # save the current context + std %r4, 176(%r3) # save the address of the function supposed to be run + ld %r0, 184(%r3) # load the stack base + + li %r4, 56 + subf %r1, %r4, %r1 # reserve space on stack + stw %r3, 48(%r1) # store pointer to fcontext_t on stack + mflr %r4 # load LR + stw %r4, 40(%r1) # store LR on stack + mr. %r3, %r0 # context stack as arg to align_stack + bl align_stack@plt # call align_stack + mr. %r0, %r3 # load result into R0 + lwz %r4, 40(%r1) # pop LR from stack + mtlr %r4 # restore LR + lwz %r3, 48(%r1) # pop pointer to fcontext_t from stack + addi %r1, %r1, 56 # release space on stack + + li %r4, 64 + subf %r0, %r4, %r0 # 64 bytes on stack for parameter area (== 8 registers) + std %r0, 152(%r3) # save the stack base + + mflr %r0 # load LR + bl 1f # jump to label 1 +1: + mflr %r4 # load LR + addi %r4, %r4, finish - 1b # calulate absolute address of finish + mtlr %r0 # restore LR + std %r4, 168(%r3) # save address of finish + + li %r3, 0 # set return value to zero + blr + +finish: + li %r3, 0 # set return value to zero + bl _exit@plt # exit application +.size .make_fcontext, .-.make_fcontext diff --git a/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm b/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm new file mode 100644 index 0000000000..f1f8ca12a7 --- /dev/null +++ b/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm @@ -0,0 +1,207 @@ + +; 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) + +; ---------------------------------------------------------------------------------- +; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +; ---------------------------------------------------------------------------------- +; | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | +; ---------------------------------------------------------------------------------- +; | R12 | R13 | R14 | R15 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | +; ---------------------------------------------------------------------------------- +; | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | +; ---------------------------------------------------------------------------------- +; | RDI | RSI | RBX | RBP | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 16 | 17 | 18 | 19 | | +; ---------------------------------------------------------------------------------- +; | 0x40 | 0x44 | 0x48 | 0x4c | | +; ---------------------------------------------------------------------------------- +; | RSP | RIP | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 20 | 21 | 22 | 23 | | +; ---------------------------------------------------------------------------------- +; | 0x50 | 0x54 | 0x58 | 0x5c | | +; ---------------------------------------------------------------------------------- +; | sbase | slimit | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 24 | 25 | | +; ---------------------------------------------------------------------------------- +; | 0x60 | 0x64 | | +; ---------------------------------------------------------------------------------- +; | fbr_strg | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 26 | 27 | 28 | 29 | | +; ---------------------------------------------------------------------------------- +; | 0x68 | 0x6c | 0x70 | 0x74 | | +; ---------------------------------------------------------------------------------- +; | fc_mxcsr|fc_x87_cw| fc_xmm | | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | +; ---------------------------------------------------------------------------------- +; | 0x78 | 0x7c | 0x80 | 0x84 | 0x88 | 0x8c | 0x90 | 0x94 | +; ---------------------------------------------------------------------------------- +; | XMM6 | XMM7 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | +; ---------------------------------------------------------------------------------- +; | 0x98 | 0x9c | 0x100 | 0x104 | 0x108 | 0x10c | 0x110 | 0x114 | +; ---------------------------------------------------------------------------------- +; | XMM8 | XMM9 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | +; ---------------------------------------------------------------------------------- +; | 0x118 | 0x11c | 0x120 | 0x124 | 0x128 | 0x12c | 0x130 | 0x134 | +; ---------------------------------------------------------------------------------- +; | XMM10 | XMM11 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | +; ---------------------------------------------------------------------------------- +; | 0x138 | 0x13c | 0x140 | 0x144 | 0x148 | 0x14c | 0x150 | 0x154 | +; ---------------------------------------------------------------------------------- +; | XMM12 | XMM13 | +; ---------------------------------------------------------------------------------- +; ---------------------------------------------------------------------------------- +; | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | +; ---------------------------------------------------------------------------------- +; | 0x158 | 0x15c | 0x160 | 0x164 | 0x168 | 0x16c | 0x170 | 0x174 | +; ---------------------------------------------------------------------------------- +; | XMM14 | XMM15 | +; ---------------------------------------------------------------------------------- + +EXTERN _exit:PROC ; standard C library function +EXTERN align_stack:PROC ; stack alignment +EXTERN seh_fcontext:PROC ; exception handler +.code + +jump_fcontext PROC EXPORT FRAME:seh_fcontext + .endprolog + + mov [rcx], r12 ; save R12 + mov [rcx+08h], r13 ; save R13 + mov [rcx+010h], r14 ; save R14 + mov [rcx+018h], r15 ; save R15 + mov [rcx+020h], rdi ; save RDI + mov [rcx+028h], rsi ; save RSI + mov [rcx+030h], rbx ; save RBX + mov [rcx+038h], rbp ; save RBP + + mov r10, gs:[030h] ; load NT_TIB + mov rax, [r10+08h] ; load current stack base + mov [rcx+050h], rax ; save current stack base + mov rax, [r10+010h] ; load current stack limit + mov [rcx+058h], rax ; save current stack limit + mov rax, [r10+018h] ; load fiber local storage + mov [rcx+060h], rax ; save fiber local storage + + test r9, r9 + je nxt + + stmxcsr [rcx+068h] ; save MMX control and status word + fnstcw [rcx+06ch] ; save x87 control word + mov r10, [rcx+070h] ; 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 + + ldmxcsr [rdx+068h] ; restore MMX control and status word + fldcw [rdx+06ch] ; restore x87 control word + mov r10, [rdx+070h] ; 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] +nxt: + + lea rax, [rsp+08h] ; exclude the return address + mov [rcx+040h], rax ; save as stack pointer + mov rax, [rsp] ; load return address + mov [rcx+048h], rax ; save return address + + mov r12, [rdx] ; restore R12 + mov r13, [rdx+08h] ; restore R13 + mov r14, [rdx+010h] ; restore R14 + mov r15, [rdx+018h] ; restore R15 + mov rdi, [rdx+020h] ; restore RDI + mov rsi, [rdx+028h] ; restore RSI + mov rbx, [rdx+030h] ; restore RBX + mov rbp, [rdx+038h] ; restore RBP + + mov r10, gs:[030h] ; load NT_TIB + mov rax, [rdx+050h] ; load stack base + mov [r10+08h], rax ; restore stack base + mov rax, [rdx+058h] ; load stack limit + mov [r10+010h], rax ; restore stack limit + mov rax, [rdx+060h] ; load fiber local storage + mov [r10+018h], rax ; restore fiber local storage + + mov rsp, [rdx+040h] ; restore RSP + mov r10, [rdx+048h] ; fetch the address to returned to + + mov rax, r8 ; use third arg as return value after jump + mov rcx, r8 ; use third arg as first arg in context function + + 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 + .endprolog ; .xdata for a function's structured exception handling unwind behavior + + mov [rcx], rcx ; store the address of current context + mov [rcx+048h], rdx ; save the address of the function supposed to run + mov rdx, [rcx+050h] ; load the address where the context stack beginns + + push rcx ; save pointer to fcontext_t + sub rsp, 028h ; reserve shadow space for align_stack + mov rcx, rdx ; stack pointer as arg for align_stack + mov [rsp+8], rcx + call align_stack ; align stack + mov rdx, rax ; begin of aligned 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 beginns + + stmxcsr [rcx+068h] ; save MMX control and status word + fnstcw [rcx+06ch] ; 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 + + xor rax, rax ; set RAX to zero + ret + +finish: + xor rcx, rcx + mov [rsp+08h], rcx + call _exit ; exit application + hlt +make_fcontext ENDP +END diff --git a/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S b/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S new file mode 100644 index 0000000000..ad2d42b46c --- /dev/null +++ b/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S @@ -0,0 +1,116 @@ +/* + 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) +*/ + +/**************************************************************************************** + * * + * ---------------------------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ---------------------------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * + * ---------------------------------------------------------------------------------- * + * | RBX | R12 | R13 | R14 | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ---------------------------------------------------------------------------------- * + * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * + * ---------------------------------------------------------------------------------- * + * | R15 | RBP | RSP | RIP | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 16 | 17 | 18 | 19 | | * + * ---------------------------------------------------------------------------------- * + * | 0x40 | 0x44 | 0x48 | 0x4c | | * + * ---------------------------------------------------------------------------------- * + * | sbase | slimit | | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 20 | 21 | | * + * ---------------------------------------------------------------------------------- * + * | 0x50 | 0x54 | | * + * ---------------------------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * ---------------------------------------------------------------------------------- * + * * + * **************************************************************************************/ + +.text +.globl jump_fcontext +.type jump_fcontext,@function +.align 16 +jump_fcontext: + movq %rbx, (%rdi) /* save RBX */ + movq %r12, 0x8(%rdi) /* save R12 */ + movq %r13, 0x10(%rdi) /* save R13 */ + movq %r14, 0x18(%rdi) /* save R14 */ + movq %r15, 0x20(%rdi) /* save R15 */ + movq %rbp, 0x28(%rdi) /* save RBP */ + + cmp $0, %rcx + je 1f + + stmxcsr 0x50(%rdi) /* save MMX control and status word */ + fnstcw 0x54(%rdi) /* save x87 control word */ + + ldmxcsr 0x50(%rsi) /* restore MMX control and status word */ + fldcw 0x54(%rsi) /* restore x87 control word */ +1: + + leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */ + movq %rax, 0x30(%rdi) /* save as stack pointer */ + movq (%rsp), %rax /* save return address */ + movq %rax, 0x38(%rdi) /* save return address as RIP */ + + movq (%rsi), %rbx /* restore RBX */ + movq 0x8(%rsi), %r12 /* restore R12 */ + movq 0x10(%rsi), %r13 /* restore R13 */ + movq 0x18(%rsi), %r14 /* restore R14 */ + movq 0x20(%rsi), %r15 /* restore R15 */ + movq 0x28(%rsi), %rbp /* restore RBP */ + + movq 0x30(%rsi), %rsp /* restore RSP */ + movq 0x38(%rsi), %rcx /* fetch the address to return to */ + + movq %rdx, %rax /* use third arg as return value after jump */ + movq %rdx, %rdi /* use third arg as first arg in context function */ + + jmp *%rcx /* indirect jump to context */ +.size jump_fcontext,.-jump_fcontext + +.text +.globl make_fcontext +.type make_fcontext,@function +.align 16 +make_fcontext: + movq %rdi, (%rdi) /* save the address of passed context */ + movq %rsi, 0x38(%rdi) /* save the address of the context function */ + movq 0x40(%rdi), %rdx /* load the stack base */ + + pushq %rdi /* save pointer to fcontext_t */ + movq %rdx, %rdi /* stack pointer as arg for align_stack */ + call align_stack@PLT /* align stack */ + movq %rax, %rdx /* begin of aligned stack */ + popq %rdi /* restore pointer to fcontext_t */ + + leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) & 15 == 0 */ + movq %rdx, 0x30(%rdi) /* save the algined 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 + ret + +finish: + xorq %rdi, %rdi /* exit code is zero */ + call _exit@PLT /* exit application */ + hlt +.size make_fcontext,.-make_fcontext + diff --git a/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S b/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S new file mode 100644 index 0000000000..eea76e455a --- /dev/null +++ b/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S @@ -0,0 +1,111 @@ +/* + 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) +*/ + +/**************************************************************************************** + * * + * ---------------------------------------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ---------------------------------------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * + * ---------------------------------------------------------------------------------- * + * | RBX | R12 | R13 | R14 | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ---------------------------------------------------------------------------------- * + * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * + * ---------------------------------------------------------------------------------- * + * | R15 | RBP | RSP | RIP | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 16 | 17 | 18 | 19 | | * + * ---------------------------------------------------------------------------------- * + * | 0x40 | 0x44 | 0x48 | 0x4c | | * + * ---------------------------------------------------------------------------------- * + * | sbase | slimit | | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 20 | 21 | | * + * ---------------------------------------------------------------------------------- * + * | 0x50 | 0x54 | | * + * ---------------------------------------------------------------------------------- * + * | fc_mxcsr|fc_x87_cw| | * + * ---------------------------------------------------------------------------------- * + * * + * **************************************************************************************/ + +.text +.globl _jump_fcontext +.align 8 +_jump_fcontext: + movq %rbx, (%rdi) /* save RBX */ + movq %r12, 0x8(%rdi) /* save R12 */ + movq %r13, 0x10(%rdi) /* save R13 */ + movq %r14, 0x18(%rdi) /* save R14 */ + movq %r15, 0x20(%rdi) /* save R15 */ + movq %rbp, 0x28(%rdi) /* save RBP */ + + cmp $0, %rcx + je 1f + + stmxcsr 0x50(%rdi) /* save MMX control and status word */ + fnstcw 0x54(%rdi) /* save x87 control word */ + + ldmxcsr 0x50(%rsi) /* restore MMX control and status word */ + fldcw 0x54(%rsi) /* restore x87 control word */ +1: + + leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */ + movq %rax, 0x30(%rdi) /* save as stack pointer */ + movq (%rsp), %rax /* save return address */ + movq %rax, 0x38(%rdi) /* save return address as RIP */ + + movq (%rsi), %rbx /* restore RBX */ + movq 0x8(%rsi), %r12 /* restore R12 */ + movq 0x10(%rsi), %r13 /* restore R13 */ + movq 0x18(%rsi), %r14 /* restore R14 */ + movq 0x20(%rsi), %r15 /* restore R15 */ + movq 0x28(%rsi), %rbp /* restore RBP */ + + movq 0x30(%rsi), %rsp /* restore RSP */ + movq 0x38(%rsi), %rcx /* fetch the address to return to */ + + movq %rdx, %rax /* use third arg as return value after jump */ + movq %rdx, %rdi /* use third arg as first arg in context function */ + + jmp *%rcx /* indirect jump to context */ + +.text +.globl _make_fcontext +.align 8 +_make_fcontext: + movq %rdi, (%rdi) /* save the address of current context */ + movq %rsi, 0x38(%rdi) /* save the address of the function supposed to run */ + movq 0x40(%rdi), %rdx /* load the stack base */ + + pushq %rdi /* save pointer to fcontext_t */ + movq %rdx, %rdi /* stack pointer as arg for align_stack */ + call _align_stack /* align stack */ + movq %rax, %rdx /* begin of aligned stack */ + popq %rdi /* restore pointer to fcontext_t */ + + leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) % 16 == 0 */ + movq %rdx, 0x30(%rdi) /* save the address */ + + 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 */ + ret + +finish: + xorq %rdi, %rdi /* exit code is zero */ + call _exit /* exit application */ + hlt diff --git a/libs/context/src/fcontext.cpp b/libs/context/src/fcontext.cpp new file mode 100644 index 0000000000..596cbd8e8a --- /dev/null +++ b/libs/context/src/fcontext.cpp @@ -0,0 +1,36 @@ + +// 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/fcontext.hpp> + +#include <cstddef> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { +namespace detail { + +extern "C" BOOST_CONTEXT_DECL +void * BOOST_CONTEXT_CALLDECL align_stack( void * vp) +{ + void * base = vp; + if ( 0 != ( ( ( uintptr_t) base) & 15) ) + base = ( char * ) ( ( ( ( uintptr_t) base) - 15) & ~0x0F); + return base; +} + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif diff --git a/libs/context/src/seh.cpp b/libs/context/src/seh.cpp new file mode 100644 index 0000000000..9363805cf5 --- /dev/null +++ b/libs/context/src/seh.cpp @@ -0,0 +1,83 @@ + +// 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 + +extern "C" { + +#include <stddef.h> +#include <stdio.h> + +#include <excpt.h> +#include <windows.h> +#include <winnt.h> + +#if defined(_MSC_VER) +# define SNPRINTF _snprintf +#else +# define SNPRINTF snprintf +#endif + +static const char * exception_description( + _EXCEPTION_RECORD const* record, char * description, size_t len) +{ + const DWORD code = record->ExceptionCode; + const ULONG_PTR * info = record->ExceptionInformation; + + switch ( code) + { + case EXCEPTION_ACCESS_VIOLATION: + { + const char * accessType = ( info[0]) ? "writing" : "reading"; + const ULONG_PTR address = info[1]; + SNPRINTF( description, len, "Access violation %s %p", accessType, reinterpret_cast< void * >( address) ); + return description; + } + case EXCEPTION_DATATYPE_MISALIGNMENT: return "Datatype misalignment"; + case EXCEPTION_BREAKPOINT: return "Breakpoint"; + case EXCEPTION_SINGLE_STEP: return "Single step"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "Array bounds exceeded"; + case EXCEPTION_FLT_DENORMAL_OPERAND: return "FPU denormal operand"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "FPU divide by zero"; + case EXCEPTION_FLT_INEXACT_RESULT: return "FPU inexact result"; + case EXCEPTION_FLT_INVALID_OPERATION: return "FPU invalid operation"; + case EXCEPTION_FLT_OVERFLOW: return "FPU overflow"; + case EXCEPTION_FLT_STACK_CHECK: return "FPU stack check"; + case EXCEPTION_FLT_UNDERFLOW: return "FPU underflow"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: return "Integer divide by zero"; + case EXCEPTION_INT_OVERFLOW: return "Integer overflow"; + case EXCEPTION_PRIV_INSTRUCTION: return "Privileged instruction"; + case EXCEPTION_IN_PAGE_ERROR: return "In page error"; + case EXCEPTION_ILLEGAL_INSTRUCTION: return "Illegal instruction"; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "Noncontinuable exception"; + case EXCEPTION_STACK_OVERFLOW: return "Stack overflow"; + case EXCEPTION_INVALID_DISPOSITION: return "Invalid disposition"; + case EXCEPTION_GUARD_PAGE: return "Guard page"; + case EXCEPTION_INVALID_HANDLE: return "Invalid handle"; + } + + SNPRINTF( description, len, "Unknown (0x%08lX)", code); + return description; +} + +EXCEPTION_DISPOSITION seh_fcontext( + struct _EXCEPTION_RECORD * record, + void *, + struct _CONTEXT *, + void *) +{ + char description[255]; + + fprintf( stderr, "exception: %s (%08lX)\n", + exception_description( record, description, sizeof( description) ), + record->ExceptionCode); + + ExitProcess( -1); + + return ExceptionContinueSearch; // never reached +} + +} diff --git a/libs/context/src/stack_allocator_posix.cpp b/libs/context/src/stack_allocator_posix.cpp new file mode 100644 index 0000000000..a373e56d03 --- /dev/null +++ b/libs/context/src/stack_allocator_posix.cpp @@ -0,0 +1,84 @@ + +// 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 <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +} + +#include <stdexcept> + +#include <boost/config.hpp> +#include <boost/assert.hpp> +#include <boost/format.hpp> + +#include <boost/context/stack_utils.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace ctx { + +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 +1 for guard page + std::size_t size_ = pages * pagesize(); + + 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(); + + 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); // add +1 for guard page + 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 diff --git a/libs/context/src/stack_allocator_windows.cpp b/libs/context/src/stack_allocator_windows.cpp new file mode 100644 index 0000000000..518239f0e3 --- /dev/null +++ b/libs/context/src/stack_allocator_windows.cpp @@ -0,0 +1,86 @@ + +// 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 <windows.h> +} + +#include <stdexcept> + +#include <boost/config.hpp> +#include <boost/assert.hpp> +#include <boost/cstdint.hpp> +#include <boost/format.hpp> + +#include <boost/context/stack_utils.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +# if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4244 4267) +# endif + +namespace boost { +namespace ctx { + +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 +1 for guard page + std::size_t size_ = pages * pagesize(); + +#ifndef BOOST_CONTEXT_FIBER + void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE); + if ( ! limit) throw std::bad_alloc(); + + 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_; +#endif +} + +void +stack_allocator::deallocate( void * vp, std::size_t size) const +{ + if ( vp) + { + const std::size_t pages( page_count( size) + 1); // add +1 for guard page + std::size_t size_ = pages * pagesize(); + BOOST_ASSERT( 0 < size && 0 < size_); + void * limit = static_cast< char * >( vp) - size_; + ::VirtualFree( limit, 0, MEM_RELEASE); + } +} + +}} + +# if defined(BOOST_MSVC) +# pragma warning(pop) +# endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif diff --git a/libs/context/src/stack_utils_posix.cpp b/libs/context/src/stack_utils_posix.cpp new file mode 100644 index 0000000000..6d7c9aecc2 --- /dev/null +++ b/libs/context/src/stack_utils_posix.cpp @@ -0,0 +1,80 @@ + +// 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_utils.hpp> + +extern "C" { +#include <signal.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <unistd.h> +} + +#include <cmath> + +#include <boost/assert.hpp> + +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; +} + +} + +namespace boost { +namespace ctx { + +BOOST_CONTEXT_DECL +std::size_t default_stacksize() +{ + static std::size_t size = 256 * 1024; + return size; +} + +BOOST_CONTEXT_DECL +std::size_t minimum_stacksize() +{ return SIGSTKSZ; } + +BOOST_CONTEXT_DECL +std::size_t maximum_stacksize() +{ + BOOST_ASSERT( ! is_stack_unbound() ); + return static_cast< std::size_t >( stacksize_limit().rlim_max); +} + +BOOST_CONTEXT_DECL +bool is_stack_unbound() +{ return RLIM_INFINITY == stacksize_limit().rlim_max; } + +BOOST_CONTEXT_DECL +std::size_t pagesize() +{ + static std::size_t pagesize( ::getpagesize() ); + return pagesize; +} + +BOOST_CONTEXT_DECL +std::size_t page_count( std::size_t stacksize) +{ + return static_cast< std::size_t >( + std::ceil( + static_cast< float >( stacksize) / pagesize() ) ); +} + +}} diff --git a/libs/context/src/stack_utils_windows.cpp b/libs/context/src/stack_utils_windows.cpp new file mode 100644 index 0000000000..373033dac2 --- /dev/null +++ b/libs/context/src/stack_utils_windows.cpp @@ -0,0 +1,84 @@ + +// 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_utils.hpp> + +extern "C" { +#include <windows.h> +} + +#include <cmath> +#include <csignal> + +#include <boost/assert.hpp> + +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 { + +BOOST_CONTEXT_DECL +std::size_t default_stacksize() +{ + static std::size_t size = 256 * 1024; + return size; +} + +BOOST_CONTEXT_DECL +std::size_t minimum_stacksize() +{ + static std::size_t stacksize( + static_cast< std::size_t >( system_info().dwAllocationGranularity) ); + return stacksize; +} + +BOOST_CONTEXT_DECL +std::size_t maximum_stacksize() +{ + BOOST_ASSERT( ! is_stack_unbound() ); + static std::size_t stacksize = 8 * 1024 * 1024; + return stacksize; +} + +// 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() +{ + static std::size_t pagesize( + static_cast< std::size_t >( system_info().dwPageSize) ); + return pagesize; +} + +BOOST_CONTEXT_DECL +std::size_t page_count( std::size_t stacksize) +{ + return static_cast< std::size_t >( + std::ceil( + static_cast< float >( stacksize) / pagesize() ) ); +} + +}} diff --git a/libs/context/test/Jamfile.v2 b/libs/context/test/Jamfile.v2 new file mode 100644 index 0000000000..d973dc44ee --- /dev/null +++ b/libs/context/test/Jamfile.v2 @@ -0,0 +1,25 @@ +# Boost.Context Library Tests Jamfile + +# 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) + +import common ; +import feature ; +import indirect ; +import modules ; +import os ; +import testing ; +import toolset ; + +project boost/context/test + : requirements + <library>../../test/build//boost_unit_test_framework + <library>/boost/context//boost_context + <link>static + ; + +test-suite "context" : + [ run test_context.cpp ] + ; diff --git a/libs/context/test/test_context.cpp b/libs/context/test/test_context.cpp new file mode 100644 index 0000000000..42f09eac84 --- /dev/null +++ b/libs/context/test/test_context.cpp @@ -0,0 +1,190 @@ + +// 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) + +#include <iostream> +#include <sstream> +#include <stdexcept> +#include <string> +#include <utility> + +#include <boost/assert.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/utility.hpp> + +#include <boost/context/all.hpp> + +namespace ctx = boost::ctx; + +ctx::fcontext_t fcm, fc1, fc2; +int value1 = 0; +std::string value2; +double value3 = 0.; + +void f1( intptr_t) +{ + ++value1; + ctx::jump_fcontext( & fc1, & fcm, 0); +} + +void f3( intptr_t) +{ + ++value1; + ctx::jump_fcontext( & fc1, & fcm, 0); + ++value1; + ctx::jump_fcontext( & fc1, & fcm, 0); +} + +void f4( intptr_t) +{ + ctx::jump_fcontext( & fc1, & fcm, 7); +} + +void f5( intptr_t arg) +{ + ctx::jump_fcontext( & fc1, & fcm, arg); +} + +void f6( intptr_t arg) +{ + 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); + res = data.first + data.second; + ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) res); +} + +void f7( intptr_t arg) +{ + try + { throw std::runtime_error( ( char *) arg); } + catch ( std::runtime_error const& e) + { value2 = e.what(); } + ctx::jump_fcontext( & fc1, & fcm, arg); +} + +void f8( intptr_t arg) +{ + double d = * ( double *) arg; + d += 3.45; + value3 = d; + ctx::jump_fcontext( & fc1, & fcm, 0); +} + +void test_start() +{ + value1 = 0; + + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() ); + fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc1, f1); + + BOOST_CHECK_EQUAL( 0, value1); + ctx::jump_fcontext( & fcm, & fc1, 0); + BOOST_CHECK_EQUAL( 1, value1); +} + +void test_jump() +{ + value1 = 0; + + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() ); + fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc1, f3); + + BOOST_CHECK_EQUAL( 0, value1); + ctx::jump_fcontext( & fcm, & fc1, 0); + BOOST_CHECK_EQUAL( 1, value1); + ctx::jump_fcontext( & fcm, & fc1, 0); + BOOST_CHECK_EQUAL( 2, value1); +} + +void test_result() +{ + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() ); + fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + ctx::make_fcontext( & fc1, f4); + + int result = ( int) ctx::jump_fcontext( & fcm, & fc1, 0); + BOOST_CHECK_EQUAL( 7, result); +} + +void test_arg() +{ + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() ); + fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + int i = 7; + ctx::make_fcontext( & fc1, f5); + + int result = ( int) ctx::jump_fcontext( & fcm, & fc1, i); + BOOST_CHECK_EQUAL( i, result); +} + +void test_transfer() +{ + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() ); + fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + std::pair< int, int > data = std::make_pair( 3, 7); + ctx::make_fcontext( & fc1, f6); + + int result = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & data); + BOOST_CHECK_EQUAL( 10, result); + data = std::make_pair( 7, 7); + result = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & data); + BOOST_CHECK_EQUAL( 14, result); +} + +void test_exception() +{ + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() ); + fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + const char * what = "hello world"; + ctx::make_fcontext( & fc1, f7); + + ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) what); + BOOST_CHECK_EQUAL( std::string( what), value2); +} + +void test_fp() +{ + ctx::stack_allocator alloc; + + fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() ); + fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize(); + double d = 7.13; + ctx::make_fcontext( & fc1, f8); + + ctx::jump_fcontext( & fcm, & fc1, (intptr_t) & d); + BOOST_CHECK_EQUAL( 10.58, value3); +} + +boost::unit_test::test_suite * init_unit_test_suite( int, char* []) +{ + boost::unit_test::test_suite * test = + BOOST_TEST_SUITE("Boost.Context: context test suite"); + + test->add( BOOST_TEST_CASE( & test_start) ); + test->add( BOOST_TEST_CASE( & test_jump) ); + test->add( BOOST_TEST_CASE( & test_result) ); + test->add( BOOST_TEST_CASE( & test_arg) ); + test->add( BOOST_TEST_CASE( & test_transfer) ); + test->add( BOOST_TEST_CASE( & test_exception) ); + test->add( BOOST_TEST_CASE( & test_fp) ); + + return test; +} |