summaryrefslogtreecommitdiff
path: root/libs/context/doc/stack.qbk
diff options
context:
space:
mode:
Diffstat (limited to 'libs/context/doc/stack.qbk')
-rw-r--r--libs/context/doc/stack.qbk293
1 files changed, 284 insertions, 9 deletions
diff --git a/libs/context/doc/stack.qbk b/libs/context/doc/stack.qbk
index 5d179a7c6..b0461716f 100644
--- a/libs/context/doc/stack.qbk
+++ b/libs/context/doc/stack.qbk
@@ -1,4 +1,5 @@
-[/ Copyright Oliver Kowalke 2009.
+[/
+ Copyright Oliver Kowalke 2014.
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
@@ -6,20 +7,294 @@
[section:stack Stack allocation]
-A __fcontext__ requires a stack which will be allocated/deallocated
-by a __stack_allocator__ (examples contain an implementation
-of [@boost:/libs/context/example/simple_stack_allocator.hpp
-simple_stack_allocator]).
+The memory used by the stack is allocated/deallocated via a __stack_allocator__
+which is required to model a __stack_allocator_concept__.
-[note The implementation of a __stack_allocator__ might include logic to protect
+
+[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, `sctx` is a `stack_context`, and `size` is a `std::size_t`:
+
+[table
+ [[expression][return type][notes]]
+ [
+ [`a(size)`]
+ []
+ [creates a stack allocator]
+ ]
+ [
+ [`a.allocate()`]
+ [`stack_context`]
+ [creates a stack]
+ ]
+ [
+ [`a.deallocate( sctx)`]
+ [`void`]
+ [deallocates the stack created 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 `stack_context` not set by `allocate()`
+results in undefined behaviour.]
+
[note The stack is not required to be aligned; alignment takes place inside
-__make_fcontext__.]
+__econtext__.]
-[note Depending on the architecture __stack_allocator__ returns an address from
-the top of the stack (grows downwards) or the bottom of the stack (grows
+[note Depending on the architecture `allocate()` stores an address from the
+top of the stack (growing downwards) or the bottom of the stack (growing
upwards).]
+
+[section:protected_fixedsize Class ['protected_fixedsize]]
+
+__boost_context__ provides the class __protected_fixedsize__ which models
+the __stack_allocator_concept__.
+It appends a guard page at the end of each stack to protect against exceeding
+the stack. If the guard page is accessed (read or write operation) a
+segmentation fault/access violation is generated by the operating system.
+
+[important Using __protected_fixedsize__ is expensive. That is, launching a
+new coroutine with a new stack is expensive; the allocated stack is just as
+efficient to use as any other stack.]
+
+[note The appended `guard page` is [*not] mapped to physical memory, only
+virtual addresses are used.]
+
+ #include <boost/context/protected_fixedsize.hpp>
+
+ template< typename traitsT >
+ struct basic_protected_fixedsize
+ {
+ typedef traitT traits_type;
+
+ basic_protected_fixesize(std::size_t size = traits_type::default_size());
+
+ stack_context allocate();
+
+ void deallocate( stack_context &);
+ }
+
+ typedef basic_protected_fixedsize< stack_traits > protected_fixedsize
+
+[heading `stack_context allocate()`]
+[variablelist
+[[Preconditions:] [`traits_type::minimum:size() <= size` and
+`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`.]]
+[[Effects:] [Allocates memory of at least `size` Bytes and stores a pointer
+to the stack and its actual size in `sctx`. Depending
+on the architecture (the stack grows downwards/upwards) the stored address is
+the highest/lowest address of the stack.]]
+]
+
+[heading `void deallocate( stack_context & sctx)`]
+[variablelist
+[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum:size() <= sctx.size` and
+`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`.]]
+[[Effects:] [Deallocates the stack space.]]
+]
+
+[endsect]
+
+
+[section:fixedsize Class ['fixedsize_stack]]
+
+__boost_context__ provides the class __fixedsize__ which models
+the __stack_allocator_concept__.
+In contrast to __protected_fixedsize__ it does not append a guard page at the
+end of each stack. The memory is simply managed by `std::malloc()` and
+`std::free()`.
+
+ #include <boost/context/fixedsize_stack.hpp>
+
+ template< typename traitsT >
+ struct basic_fixedsize_stack
+ {
+ typedef traitT traits_type;
+
+ basic_fixesize_stack(std::size_t size = traits_type::default_size());
+
+ stack_context allocate();
+
+ void deallocate( stack_context &);
+ }
+
+ typedef basic_fixedsize_stack< stack_traits > fixedsize_stack;
+
+[heading `stack_context allocate()`]
+[variablelist
+[[Preconditions:] [`traits_type::minimum:size() <= size` and
+`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`.]]
+[[Effects:] [Allocates memory of at least `size` Bytes and stores a pointer to
+the stack and its actual size in `sctx`. Depending on the architecture (the
+stack grows downwards/upwards) the stored address is the highest/lowest
+address of the stack.]]
+]
+
+[heading `void deallocate( stack_context & sctx)`]
+[variablelist
+[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum:size() <= sctx.size` and
+`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`.]]
+[[Effects:] [Deallocates the stack space.]]
+]
+
+[endsect]
+
+
+[section:segmented Class ['segmented_stack]]
+
+__boost_context__ supports usage of a __segmented__, e. g. the size of
+the stack grows on demand. The coroutine is created with a minimal stack size
+and will be increased as required.
+Class __segmented__ models the __stack_allocator_concept__.
+In contrast to __protected_fixedsize__ and __fixedsize__ it creates a
+stack which grows on demand.
+
+[note Segmented stacks are currently only supported by [*gcc] from version
+[*4.7] [*clang] from version [*3.4] onwards. In order to use a
+__segmented_stack__ __boost_context__ must be built with
+[*toolset=gcc segmented-stacks=on] at b2/bjam command-line. Applications
+must be compiled with compiler-flags
+[*-fsplit-stack -DBOOST_USE_SEGMENTED_STACKS].]
+
+ #include <boost/context/segmented_stack.hpp>
+
+ template< typename traitsT >
+ struct basic_segmented_stack
+ {
+ typedef traitT traits_type;
+
+ basic_segmented_stack(std::size_t size = traits_type::default_size());
+
+ stack_context allocate();
+
+ void deallocate( stack_context &);
+ }
+
+ typedef basic_segmented_stack< stack_traits > segmented_stack;
+
+[heading `stack_context allocate()`]
+[variablelist
+[[Preconditions:] [`traits_type::minimum:size() <= size` and
+`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`.]]
+[[Effects:] [Allocates memory of at least `size` Bytes and stores a pointer to
+the stack and its actual size in `sctx`. Depending on the architecture (the
+stack grows downwards/upwards) the stored address is the highest/lowest
+address of the stack.]]
+]
+
+[heading `void deallocate( stack_context & sctx)`]
+[variablelist
+[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum:size() <= sctx.size` and
+`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`.]]
+[[Effects:] [Deallocates the stack space.]]
+]
+
+[endsect]
+
+
+[section:stack_traits Class ['stack_traits]]
+
+['stack_traits] models a __stack_traits__ providing a way to access certain
+properites defined by the enironment. Stack allocators use __stack_traits__ to
+allocate stacks.
+
+ #include <boost/context/stack_traits.hpp>
+
+ struct stack_traits
+ {
+ static bool is_unbounded() noexcept;
+
+ static std::size_t page_size() noexcept;
+
+ static std::size_t default_size() noexcept;
+
+ static std::size_t minimum_size() noexcept;
+
+ static std::size_t maximum_size() noexcept;
+ }
+
+
+[heading `static bool is_unbounded()`]
+[variablelist
+[[Returns:] [Returns `true` if the environment defines no limit for the size of
+a stack.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `static std::size_t page_size()`]
+[variablelist
+[[Returns:] [Returns the page size in bytes.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `static std::size_t default_size()`]
+[variablelist
+[[Returns:] [Returns a default stack size, which may be platform specific.
+If the stack is unbounded then the present implementation returns the maximum of
+`64 kB` and `minimum_size()`.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `static std::size_t minimum_size()`]
+[variablelist
+[[Returns:] [Returns the minimum size in bytes of stack defined by the
+environment (Win32 4kB/Win64 8kB, defined by rlimit on POSIX).]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `static std::size_t maximum_size()`]
+[variablelist
+[[Preconditions:] [`is_unbounded()` returns `false`.]]
+[[Returns:] [Returns the maximum size in bytes of stack defined by the
+environment.]]
+[[Throws:] [Nothing.]]
+]
+
+
+[endsect]
+
+
+[section:stack_context Class ['stack_context]]
+
+__boost_context__ provides the class __stack_context__ which will contain
+the stack pointer and the size of the stack.
+In case of a __segmented__, __stack_context__ contains some extra control
+structures.
+
+ struct stack_context
+ {
+ void * sp;
+ std::size_t size;
+
+ // might contain additional control structures
+ // for segmented stacks
+ }
+
+[heading `void * sp`]
+[variablelist
+[[Value:] [Pointer to the beginning of the stack.]]
+]
+
+[heading `std::size_t size`]
+[variablelist
+[[Value:] [Actual size of the stack.]]
+]
+
+[endsect]
+
+
+[section:valgrind Support for valgrind]
+
+Running programs that switch stacks under valgrind causes problems.
+Property (b2 command-line) `valgrind=on` let valgrind treat the memory regions
+as stack space which suppresses the errors.
+
+[endsect]
+
+
[endsect]