977ed18d
Hu Chunming
提交三方库
|
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]
|