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