• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2          Copyright Oliver Kowalke 2014.
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[section:stack Stack allocation]
9
10The memory used by the stack is allocated/deallocated via a __stack_allocator__
11which is required to model a __stack_allocator_concept__.
12
13
14[heading __stack_allocator_concept__]
15A __stack_allocator__ must satisfy the __stack_allocator_concept__ requirements
16shown in the following table, in which `a` is an object of a
17__stack_allocator__ type, `sctx` is a `stack_context`, and `size` is a `std::size_t`:
18
19[table
20    [[expression][return type][notes]]
21    [
22        [`a(size)`]
23        []
24        [creates a stack allocator]
25    ]
26    [
27        [`a.allocate()`]
28        [`stack_context`]
29        [creates a stack]
30    ]
31    [
32        [`a.deallocate( sctx)`]
33        [`void`]
34        [deallocates the stack created by `a.allocate()`]
35    ]
36]
37
38[important The implementation of `allocate()` might include logic to protect
39against exceeding the context's available stack size rather than leaving it as
40undefined behaviour.]
41
42[important Calling `deallocate()` with a `stack_context` not set by `allocate()`
43results in undefined behaviour.]
44
45[note The stack is not required to be aligned; alignment takes place inside
46__econtext__.]
47
48[note Depending on the architecture `allocate()` stores an address from the
49top of the stack (growing downwards) or the bottom of the stack (growing
50upwards).]
51
52
53[section:protected_fixedsize Class ['protected_fixedsize]]
54
55__boost_coroutine__ provides the class __protected_fixedsize__ which models
56the __stack_allocator_concept__.
57It appends a guard page at the end of each stack to protect against exceeding
58the stack. If the guard page is accessed (read or write operation) a
59segmentation fault/access violation is generated by the operating system.
60
61[important Using __protected_fixedsize__ is expensive. That is, launching a
62new coroutine with a new stack is expensive; the allocated stack is just as
63efficient to use as any other stack.]
64
65[note The appended `guard page` is [*not] mapped to physical memory, only
66virtual addresses are used.]
67
68        #include <boost/coroutine2/protected_fixedsize.hpp>
69
70        struct protected_fixedsize {
71            protected_fixesize(std::size_t size = traits_type::default_size());
72
73            stack_context allocate();
74
75            void deallocate( stack_context &);
76        }
77
78[heading `stack_context allocate()`]
79[variablelist
80[[Preconditions:] [`traits_type::minimum:size() <= size` and
81`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`.]]
82[[Effects:] [Allocates memory of at least `size` bytes and stores a pointer
83to the stack and its actual size in `sctx`. Depending
84on the architecture (the stack grows downwards/upwards) the stored address is
85the highest/lowest address of the stack.]]
86]
87
88[heading `void deallocate( stack_context & sctx)`]
89[variablelist
90[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum:size() <= sctx.size` and
91`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`.]]
92[[Effects:] [Deallocates the stack space.]]
93]
94
95[endsect]
96
97
98[section:pooled_fixedsize Class ['pooled_fixedsize_stack]]
99
100__boost_coroutine__ provides the class __pooled_fixedsize__ which models
101the __stack_allocator_concept__.
102In contrast to __protected_fixedsize__ it does not append a guard page at the
103end of each stack. The memory is managed internally by
104[@http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html `boost::pool<>`].
105
106        #include <boost/coroutine2/pooled_fixedsize_stack.hpp>
107
108        struct pooled_fixedsize_stack {
109            pooled_fixedsize_stack(std::size_t size = traits_type::default_size());
110
111            stack_context allocate();
112
113            void deallocate( stack_context &);
114        }
115
116[heading `pooled_fixedsize_stack(std::size_t stack_size, std::size_t next_size, std::size_t max_size)`]
117[variablelist
118[[Preconditions:] [`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= stack_size)`
119and `0 < nest_size`.]]
120[[Effects:] [Allocates memory of at least `stack_size` Bytes and stores a pointer to
121the stack and its actual size in `sctx`. Depending on the architecture (the
122stack grows downwards/upwards) the stored address is the highest/lowest
123address of the stack. Argument `next_size` determines the number of stacks to
124request from the system the first time that `*this` needs to allocate system
125memory. The third argument `max_size` controls how many memory might be
126allocated for stacks - a value of zero means no uper limit.]]
127]
128
129[heading `stack_context allocate()`]
130[variablelist
131[[Preconditions:] [`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`.]]
132[[Effects:] [Allocates memory of at least `size` bytes and stores a pointer to
133the stack and its actual size in `sctx`. Depending on the architecture (the
134stack grows downwards/upwards) the stored address is the highest/lowest
135address of the stack.]]
136]
137
138[heading `void deallocate( stack_context & sctx)`]
139[variablelist
140[[Preconditions:] [`sctx.sp` is valid,
141`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`.]]
142[[Effects:] [Deallocates the stack space.]]
143]
144
145[endsect]
146
147
148[section:fixedsize Class ['fixedsize_stack]]
149
150__boost_coroutine__ provides the class __fixedsize__ which models
151the __stack_allocator_concept__.
152In contrast to __protected_fixedsize__ it does not append a guard page at the
153end of each stack. The memory is simply managed by `std::malloc()` and
154`std::free()`.
155
156        #include <boost/context/fixedsize_stack.hpp>
157
158        struct fixedsize_stack {
159            fixedsize_stack(std::size_t size = traits_type::default_size());
160
161            stack_context allocate();
162
163            void deallocate( stack_context &);
164        }
165
166[heading `stack_context allocate()`]
167[variablelist
168[[Preconditions:] [`traits_type::minimum:size() <= size` and
169`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`.]]
170[[Effects:] [Allocates memory of at least `size` Bytes and stores a pointer to
171the stack and its actual size in `sctx`. Depending on the architecture (the
172stack grows downwards/upwards) the stored address is the highest/lowest
173address of the stack.]]
174]
175
176[heading `void deallocate( stack_context & sctx)`]
177[variablelist
178[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum:size() <= sctx.size` and
179`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`.]]
180[[Effects:] [Deallocates the stack space.]]
181]
182
183[endsect]
184
185
186[#segmented]
187[section:segmented Class ['segmented_stack]]
188
189__boost_coroutine__ supports usage of a __segmented__, e. g. the size of
190the stack grows on demand. The coroutine is created with a minimal stack size
191and will be increased as required.
192Class __segmented__ models the __stack_allocator_concept__.
193In contrast to __protected_fixedsize__ and __fixedsize__ it creates a
194stack which grows on demand.
195
196[note Segmented stacks are currently only supported by [*gcc] from version
197[*4.7] [*clang] from version [*3.4] onwards. In order to use a
198__segmented_stack__ __boost_context__ must be built with
199property `segmented-stacks`, e.g. [*toolset=gcc segmented-stacks=on] and
200applying `BOOST_USE_SEGMENTED_STACKS` and `BOOST_USE_UCONTEXT` at b2/bjam
201command line.]
202
203
204        #include <boost/coroutine2/segmented_stack.hpp>
205
206        struct segmented_stack {
207            segmented_stack(std::size_t size = traits_type::default_size());
208
209            stack_context allocate();
210
211            void deallocate( stack_context &);
212        }
213
214[heading `stack_context allocate()`]
215[variablelist
216[[Preconditions:] [`traits_type::minimum:size() <= size` and
217`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= size)`.]]
218[[Effects:] [Allocates memory of at least `size` bytes and stores a pointer to
219the stack and its actual size in `sctx`. Depending on the architecture (the
220stack grows downwards/upwards) the stored address is the highest/lowest
221address of the stack.]]
222]
223
224[heading `void deallocate( stack_context & sctx)`]
225[variablelist
226[[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum:size() <= sctx.size` and
227`! traits_type::is_unbounded() && ( traits_type::maximum:size() >= sctx.size)`.]]
228[[Effects:] [Deallocates the stack space.]]
229]
230
231[note If the library is compiled for segmented stacks, __segmented_stack__ is the only
232available stack allocator.]
233
234[endsect]
235
236
237[section:stack_traits Class ['stack_traits]]
238
239['stack_traits] models a __stack_traits__ providing a way to access certain
240properites defined by the enironment. Stack allocators use __stack_traits__ to
241allocate stacks.
242
243        struct stack_traits
244        {
245            static bool is_unbounded() noexcept;
246
247            static std::size_t page_size() noexcept;
248
249            static std::size_t default_size() noexcept;
250
251            static std::size_t minimum_size() noexcept;
252
253            static std::size_t maximum_size() noexcept;
254        }
255
256
257[heading `static bool is_unbounded()`]
258[variablelist
259[[Returns:] [Returns `true` if the environment defines no limit for the size of
260a stack.]]
261[[Throws:] [Nothing.]]
262]
263
264[heading `static std::size_t page_size()`]
265[variablelist
266[[Returns:] [Returns the page size in bytes.]]
267[[Throws:] [Nothing.]]
268]
269
270[heading `static std::size_t default_size()`]
271[variablelist
272[[Returns:] [Returns a default stack size, which may be platform specific.
273If the stack is unbounded then the present implementation returns the maximum of
274`64 kB` and `minimum_size()`.]]
275[[Throws:] [Nothing.]]
276]
277
278[heading `static std::size_t minimum_size()`]
279[variablelist
280[[Returns:] [Returns the minimum size in bytes of stack defined by the
281environment (Win32 4kB/Win64 8kB, defined by rlimit on POSIX).]]
282[[Throws:] [Nothing.]]
283]
284
285[heading `static std::size_t maximum_size()`]
286[variablelist
287[[Preconditions:] [`is_unbounded()` returns `false`.]]
288[[Returns:] [Returns the maximum size in bytes of stack defined by the
289environment.]]
290[[Throws:] [Nothing.]]
291]
292
293
294[endsect]
295
296
297[section:stack_context Class ['stack_context]]
298
299__boost_coroutine__ provides the class __stack_context__ which will contain
300the stack pointer and the size of the stack.
301In case of a __segmented__, __stack_context__ contains some extra control
302structures.
303
304        struct stack_context
305        {
306            void    *   sp;
307            std::size_t size;
308
309            // might contain additional control structures
310            // for segmented stacks
311        }
312
313[heading `void * sp`]
314[variablelist
315[[Value:] [Pointer to the beginning of the stack.]]
316]
317
318[heading `std::size_t size`]
319[variablelist
320[[Value:] [Actual size of the stack.]]
321]
322
323[endsect]
324
325
326[section:valgrind Support for valgrind]
327
328Running programs that switch stacks under valgrind causes problems.
329Property (b2 command-line) `valgrind=on` let valgrind treat the memory regions
330as stack space which suppresses the errors.
331
332[endsect]
333
334
335[section:sanitizers Support for sanitizers]
336
337Sanitizers (GCC/Clang) are confused by the stack switches.
338The library (and Boost.Context too) is required to be compiled with property (b2 command-line)
339`context-impl=ucontext` and compilers santizer options.
340Users must define `BOOST_USE_ASAN` before including any Boost.Context headers
341when linking against Boost binaries.
342
343[endsect]
344
345
346
347[endsect]
348