1[/ 2 Copyright Oliver Kowalke 2009-2013. 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 http://www.boost.org/LICENSE_1_0.txt 6] 7 8[#stack] 9[section:stack Stack allocation] 10 11A __fiber__ uses internally an __econtext__ which manages a set of registers and a stack. 12The memory used by the stack is allocated/deallocated via a __stack_allocator__ 13which is required to model a __stack_allocator_concept__. 14 15A __stack_allocator__ can be passed to [link fiber_fiber `fiber::fiber()`] or 16to [ns_function_link fibers..async]. 17 18[#stack_allocator_concept] 19[heading stack-allocator concept] 20A __stack_allocator__ must satisfy the ['stack-allocator concept] requirements 21shown in the following table, in which `a` is an object of a 22__stack_allocator__ type, `sctx` is a __stack_context__, and `size` is a `std::size_t`: 23 24[table 25 [[expression][return type][notes]] 26 [ 27 [`a(size)`] 28 [] 29 [creates a stack allocator] 30 ] 31 [ 32 [`a.allocate()`] 33 [__stack_context__] 34 [creates a stack] 35 ] 36 [ 37 [`a.deallocate( sctx)`] 38 [`void`] 39 [deallocates the stack created by `a.allocate()`] 40 ] 41] 42 43[important The implementation of `allocate()` might include logic to protect 44against exceeding the context's available stack size rather than leaving it as 45undefined behaviour.] 46 47[important Calling `deallocate()` with a __stack_context__ not obtained from 48`allocate()` results in undefined behaviour.] 49 50[note The memory for the stack is not required to be aligned; alignment takes 51place inside __econtext__.] 52 53See also [@http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack.html Boost.Context stack allocation]. 54In particular, `traits_type` methods are as described for 55[@http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_traits.html 56`boost::context::stack_traits`]. 57 58[class_heading protected_fixedsize_stack] 59 60__boost_fiber__ provides the class __pfixedsize_stack__ which models 61the __stack_allocator_concept__. 62It appends a guard page at the end of each stack to protect against exceeding 63the stack. If the guard page is accessed (read or write operation) a 64segmentation fault/access violation is generated by the operating system. 65 66[important Using __pfixedsize_stack__ is expensive. Launching a new fiber with 67a stack of this type incurs the overhead of setting the memory protection; 68once allocated, this stack is just as efficient to use as __fixedsize_stack__.] 69 70[note The appended `guard page` is [*not] mapped to physical memory, only 71virtual addresses are used.] 72 73 #include <boost/fiber/protected_fixedsize.hpp> 74 75 namespace boost { 76 namespace fibers { 77 78 struct protected_fixedsize { 79 protected_fixesize(std::size_t size = traits_type::default_size()); 80 81 stack_context allocate(); 82 83 void deallocate( stack_context &); 84 } 85 86 }} 87 88[member_heading protected_fixedsize..allocate] 89 90 stack_context allocate(); 91 92[variablelist 93[[Preconditions:] [`traits_type::minimum_size() <= size` and 94`traits_type::is_unbounded() || ( size <= traits_type::maximum_size() )`.]] 95[[Effects:] [Allocates memory of at least `size` bytes and stores a pointer 96to the stack and its actual size in `sctx`. Depending 97on the architecture (the stack grows downwards/upwards) the stored address is 98the highest/lowest address of the stack.]] 99] 100 101[member_heading protected_fixesize..deallocate] 102 103 void deallocate( stack_context & sctx); 104 105[variablelist 106[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum_size() <= sctx.size` and 107`traits_type::is_unbounded() || ( sctx.size <= traits_type::maximum_size() )`.]] 108[[Effects:] [Deallocates the stack space.]] 109] 110 111 112[class_heading pooled_fixedsize_stack] 113 114__boost_fiber__ provides the class __ofixedsize_stack__ which models 115the __stack_allocator_concept__. 116In contrast to __pfixedsize_stack__ it does not append a guard page at the 117end of each stack. The memory is managed internally by 118[@http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html `boost::pool<>`]. 119 120 #include <boost/fiber/pooled_fixedsize_stack.hpp> 121 122 namespace boost { 123 namespace fibers { 124 125 struct pooled_fixedsize_stack { 126 pooled_fixedsize_stack(std::size_t stack_size = traits_type::default_size(), std::size_t next_size = 32, std::size_t max_size = 0); 127 128 stack_context allocate(); 129 130 void deallocate( stack_context &); 131 } 132 133 }} 134 135[hding pooled_fixedsize..Constructor] 136 137 pooled_fixedsize_stack(std::size_t stack_size, std::size_t next_size, std::size_t max_size); 138 139[variablelist 140[[Preconditions:] [`traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size)` 141and `0 < next_size`.]] 142[[Effects:] [Allocates memory of at least `stack_size` bytes and stores a pointer to 143the stack and its actual size in `sctx`. Depending on the architecture (the 144stack grows downwards/upwards) the stored address is the highest/lowest 145address of the stack. Argument `next_size` determines the number of stacks to 146request from the system the first time that `*this` needs to allocate system 147memory. The third argument `max_size` controls how much memory might be 148allocated for stacks [mdash] a value of zero means no upper limit.]] 149] 150 151[member_heading pooled_fixedsize..allocate] 152 153 stack_context allocate(); 154 155[variablelist 156[[Preconditions:] [`traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size)`.]] 157[[Effects:] [Allocates memory of at least `stack_size` bytes and stores a pointer to 158the stack and its actual size in `sctx`. Depending on the architecture (the 159stack grows downwards/upwards) the stored address is the highest/lowest 160address of the stack.]] 161] 162 163[member_heading pooled_fixesize..deallocate] 164 165 void deallocate( stack_context & sctx); 166 167[variablelist 168[[Preconditions:] [`sctx.sp` is valid, 169`traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size)`.]] 170[[Effects:] [Deallocates the stack space.]] 171] 172 173[note This stack allocator is not thread safe.] 174 175 176[class_heading fixedsize_stack] 177 178__boost_fiber__ provides the class __fixedsize_stack__ which models 179the __stack_allocator_concept__. 180In contrast to __pfixedsize_stack__ it does not append a guard page at the 181end of each stack. The memory is simply managed by `std::malloc()` and 182`std::free()`. 183 184 #include <boost/context/fixedsize_stack.hpp> 185 186 namespace boost { 187 namespace fibers { 188 189 struct fixedsize_stack { 190 fixedsize_stack(std::size_t size = traits_type::default_size()); 191 192 stack_context allocate(); 193 194 void deallocate( stack_context &); 195 } 196 197 }} 198 199[member_heading fixedsize..allocate] 200 201 stack_context allocate(); 202 203[variablelist 204[[Preconditions:] [`traits_type::minimum_size() <= size` and 205`traits_type::is_unbounded() || ( traits_type::maximum_size() >= size)`.]] 206[[Effects:] [Allocates memory of at least `size` bytes and stores a pointer to 207the stack and its actual size in `sctx`. Depending on the architecture (the 208stack grows downwards/upwards) the stored address is the highest/lowest 209address of the stack.]] 210] 211 212[member_heading fixesize..deallocate] 213 214 void deallocate( stack_context & sctx); 215 216[variablelist 217[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum_size() <= sctx.size` and 218`traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size)`.]] 219[[Effects:] [Deallocates the stack space.]] 220] 221 222 223[#segmented] 224[class_heading segmented_stack] 225 226__boost_fiber__ supports usage of a __segmented_stack__, i.e. 227the stack grows on demand. The fiber is created with a minimal stack size 228which will be increased as required. 229Class __segmented_stack__ models the __stack_allocator_concept__. 230In contrast to __pfixedsize_stack__ and __fixedsize_stack__ it creates a 231stack which grows on demand. 232 233[note Segmented stacks are currently only supported by [*gcc] from version 234[*4.7] and [*clang] from version [*3.4] onwards. In order to use a 235__segmented_stack__ __boost_fiber__ must be built with 236property `segmented-stacks`, e.g. [*toolset=gcc segmented-stacks=on] 237and applying BOOST_USE_SEGMENTED_STACKS at b2/bjam command line.] 238 239[note Segmented stacks can only be used with callcc() using property 240`context-impl=ucontext`.] 241 242 #include <boost/fiber/segmented_stack.hpp> 243 244 namespace boost { 245 namespace fibers { 246 247 struct segmented_stack { 248 segmented_stack(std::size_t stack_size = traits_type::default_size()); 249 250 stack_context allocate(); 251 252 void deallocate( stack_context &); 253 } 254 255 }} 256 257[member_heading segmented..allocate] 258 259 stack_context allocate(); 260 261[variablelist 262[[Preconditions:] [`traits_type::minimum_size() <= size` and 263`traits_type::is_unbounded() || ( traits_type::maximum_size() >= size)`.]] 264[[Effects:] [Allocates memory of at least `size` bytes and stores a pointer to 265the stack and its actual size in `sctx`. Depending on the architecture (the 266stack grows downwards/upwards) the stored address is the highest/lowest 267address of the stack.]] 268] 269 270[member_heading segmented..deallocate] 271 272 void deallocate( stack_context & sctx); 273 274 275[variablelist 276[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum_size() <= sctx.size` and 277`traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size)`.]] 278[[Effects:] [Deallocates the stack space.]] 279] 280 281[note If the library is compiled for segmented stacks, __segmented_stack__ is the only 282available stack allocator.] 283 284 285[section:valgrind Support for valgrind] 286 287Running programs that switch stacks under valgrind causes problems. 288Property (b2 command-line) `valgrind=on` let valgrind treat the memory regions 289as stack space which suppresses the errors. 290 291[endsect] 292 293[section:sanitizers Support for sanitizers] 294 295Sanitizers (GCC/Clang) are confused by the stack switches. 296The library (and Boost.Context too) is required to be compiled with property (b2 command-line) 297`context-impl=ucontext` and compilers santizer options. 298Users must define `BOOST_USE_ASAN` before including any Boost.Context headers 299when linking against Boost binaries. 300 301[endsect] 302 303[endsect] 304