Imported Upstream version 1.63.0
[platform/upstream/boost.git] / libs / context / doc / fcontext.qbk
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:context Struct fcontext_t]
9
10 Each instance of __fcontext__ represents a context (CPU registers and stack
11 space). Together with its related functions __jump_fcontext__ and
12 __make_fcontext__ it provides a execution control transfer mechanism similar
13 interface like
14 [@http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html
15 ucontext_t].
16 __fcontext__ and its functions are located in __context_ns__ and the functions
17 are declared as extern "C". 
18
19 [warning If __fcontext__ is used in a multi threaded application, it can migrated
20 between threads, but must not reference __tls__.]
21
22 [important The low level API is the part to port to new platforms.]
23
24 [note If __fls__ is used on Windows, the user is responsible for calling 
25 __fls_alloc__, __fls_free__.]
26
27
28 [heading Executing a context]
29
30 A new context supposed to execute a __context_fn__ (returning void and accepting
31 void * as argument) will be created on top of the stack (at 16 byte boundary)
32 by function __make_fcontext__.
33
34             // context-function
35             void f(intptr);
36
37             // creates a new stack
38             std::size_t size = 8192;
39             void* sp(std::malloc(size));
40
41             // context fc uses f() as context function
42             // fcontext_t is placed on top of context stack
43             // a pointer to fcontext_t is returned
44             fcontext_t fc(make_fcontext(sp,size,f));
45
46 Calling __jump_fcontext__ invokes the __context_fn__ in a newly created context
47 complete with registers, flags, stack and instruction pointers.  When control
48 should be returned to the original calling context, call __jump_fcontext__.
49 The current context information (registers, flags, and stack and instruction
50 pointers) is saved and the original context information is restored. Calling
51 __jump_fcontext__ again resumes execution in the second context after saving the
52 new state of the original context.
53
54         boost::context::fcontext_t fcm,fc1,fc2;
55
56         void f1(void *)
57         {
58             std::cout<<"f1: entered"<<std::endl;
59             std::cout<<"f1: call jump_fcontext( & fc1, fc2, 0)"<< std::endl;
60             boost::context::jump_fcontext(&fc1,fc2,0);
61             std::cout<<"f1: return"<<std::endl;
62             boost::context::jump_fcontext(&fc1,fcm,0);
63         }
64
65         void f2(void *)
66         {
67             std::cout<<"f2: entered"<<std::endl;
68             std::cout<<"f2: call jump_fcontext( & fc2, fc1, 0)"<<std::endl;
69             boost::context::jump_fcontext(&fc2,fc1,0);
70             BOOST_ASSERT(false&&!"f2: never returns");
71         }
72
73         std::size_t size(8192);
74         void* sp1(std::malloc(size));
75         void* sp2(std::malloc(size));
76
77         fc1=boost::context::make_fcontext(sp1,size,f1);
78         fc2=boost::context::make_fcontext(sp2,size,f2);
79
80         std::cout<<"main: call jump_fcontext( & fcm, fc1, 0)"<<std::endl;
81         boost::context::jump_fcontext(&fcm,fc1,0);
82
83         output:
84             main: call jump_fcontext( & fcm, fc1, 0)
85             f1: entered
86             f1: call jump_fcontext( & fc1, fc2, 0)
87             f2: entered
88             f2: call jump_fcontext( & fc2, fc1, 0)
89             f1: return
90
91 First call of __jump_fcontext__ enters the __context_fn__ `f1()` by starting
92 context fc1 (context fcm saves the registers of `main()`). For jumping between
93 context's fc1 and fc2 `jump_fcontext()` is called.
94 Because context fcm is chained to fc1, `main()` is entered (returning from
95 __jump_fcontext__) after context fc1 becomes complete (return from `f1()`).
96
97 [warning Calling __jump_fcontext__ to the same context from inside the same
98 context results in undefined behaviour.]
99
100 [important The size of the stack is required to be larger than the size of fcontext_t.]
101
102 [note In contrast to threads, which are preemtive, __fcontext__ switches are
103 cooperative (programmer controls when switch will happen). The kernel is not
104 involved in the context switches.]
105
106
107 [heading Transfer of data]
108
109 The third argument passed to __jump_fcontext__, in one context, is passed as
110 the first argument of the __context_fn__ if the context is started for the
111 first time.
112 In all following invocations of __jump_fcontext__ the void * passed to
113 __jump_fcontext__, in one context, is returned by __jump_fcontext__ in the
114 other context. 
115
116         boost::context::fcontext_t fcm,fc;
117
118         typedef std::pair<int,int> pair_t;
119
120         void f(void * param)
121         {
122             pair_t* p=(pair_t*)param;
123             p=(pair_t*)boost::context::jump_fcontext(&fc,fcm,(void *)(p->first+p->second));
124             boost::context::jump_fcontext(&fc,fcm,(void *)(p->first+p->second));
125         }
126
127         std::size_t size(8192);
128         void* sp(std::malloc(size));
129
130         pair_t p(std::make_pair(2,7));
131         fc=boost::context::make_fcontext(sp,size,f);
132
133         int res=(int)boost::context::jump_fcontext(&fcm,fc,(void *)&p);
134         std::cout<<p.first<<" + "<<p.second<<" == "<<res<<std::endl;
135
136         p=std::make_pair(5,6);
137         res=(int)boost::context::jump_fcontext(&fcm,fc,(void *)&p);
138         std::cout<<p.first<<" + "<<p.second<<" == "<<res<<std::endl;
139
140         output:
141             2 + 7 == 9
142             5 + 6 == 11
143
144
145 [heading Exceptions in __context_fn__]
146
147 If the __context_fn__ emits an exception, the behaviour is undefined.
148
149 [important __context_fn__ should wrap the code in a try/catch block.]
150 [important Do not jump from inside a catch block and then re-throw the
151 exception in another execution context.]
152
153
154 [heading Stack unwinding]
155
156 Sometimes it is necessary to unwind the stack of an unfinished context to
157 destroy local stack variables so they can release allocated resources (RAII
158 pattern). The user is responsible for this task.
159
160
161 [heading `fcontext_t` and related functions]
162
163         struct stack_t
164         {
165             void* sp;
166             std::size_t size;
167         };
168
169         typedef <opaque pointer > fcontext_t;
170
171         void * jump_fcontext(fcontext_t* ofc,fcontext_t nfc,void * vp);
172         fcontext_t make_fcontext(void* sp,std::size_t size,void(*fn)(void *));
173
174 [heading `sp`]
175 [variablelist
176 [[Member:] [Pointer to the beginning of the stack (depending of the architecture the stack grows
177 downwards or upwards).]]
178 ]
179
180 [heading `size`]
181 [variablelist
182 [[Member:] [Size of the stack in bytes.]]
183 ]
184
185 [heading `fc_stack`]
186 [variablelist
187 [[Member:] [Tracks the memory for the context's stack.]]
188 ]
189
190 [heading `void * jump_fcontext(fcontext_t* ofc,fcontext_t nfc,void * p)`]
191 [variablelist
192 [[Effects:] [Stores the current context data (stack pointer, instruction
193 pointer, and CPU registers) to `*ofc` and restores the context data from `nfc`,
194 which implies jumping to execution context `nfc`. The void * argument, `p`,
195 is passed to the current context to be returned by the most recent call to
196 `jump_fcontext()` in the same thread.]]
197 [[Returns:] [The third pointer argument passed to the most recent call to
198 `jump_fcontext()`, if any.]]
199 ]
200
201 [heading `fcontext_t make_fcontext(void* sp,std::size_t size,void(*fn)(void *))`]
202 [variablelist
203 [[Precondition:] [Stack `sp` and function pointer `fn` are valid (depending on the architecture
204 `sp` points to the top or bottom of the stack) and `size` > 0.]]
205 [[Effects:] [Creates an fcontext_t on top of the stack and prepares the stack
206 to execute the __context_fn__ `fn`.]]
207 [[Returns:][Returns a fcontext_t which is placed on the stack.]]
208 ]
209
210 [endsect]