Merge branch 'vendor/BZIP'
[dragonfly.git] / lib / libc / gen / makecontext_quick.3
1 .\"
2 .\" Copyright (c) 2015 The DragonFly Project.  All rights reserved.
3 .\"
4 .\" This code is derived from software contributed to The DragonFly Project
5 .\" by Matthew Dillon <dillon@backplane.com>
6 .\"
7 .\" Redistribution and use in source and binary forms, with or without
8 .\" modification, are permitted provided that the following conditions
9 .\" are met:
10 .\"
11 .\" 1. Redistributions of source code must retain the above copyright
12 .\"    notice, this list of conditions and the following disclaimer.
13 .\" 2. Redistributions in binary form must reproduce the above copyright
14 .\"    notice, this list of conditions and the following disclaimer in
15 .\"    the documentation and/or other materials provided with the
16 .\"    distribution.
17 .\" 3. Neither the name of The DragonFly Project nor the names of its
18 .\"    contributors may be used to endorse or promote products derived
19 .\"    from this software without specific, prior written permission.
20 .\"
21 .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 .\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25 .\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 .\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 .\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 .\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 .\" SUCH DAMAGE.
33 .\"
34 .Dd December 21, 2015
35 .Dt MAKECONTEXT_QUICK 3
36 .Os
37 .Sh NAME
38 .Nm makecontext_quick , swapcontext_quick , setcontext_quick
39 .Nd quickly modify and exchange user thread contexts
40 .Sh LIBRARY
41 .Lb libc
42 .Sh SYNOPSIS
43 .In ucontext.h
44 .Ft void
45 .Fn makecontext_quick "ucontext_t *ucp"
46 .Ft void
47 .Fn swapcontext_quick "ucontext_t *oucp" "ucontext_t *nucp"
48 .Ft void
49 .Fn setcontext_quick "ucontext_t *ucp"
50 .Sh DESCRIPTION
51 The quick context functions work similarly to the non-quick context functions
52 but are designed for proper coroutine operation and synchronous switching.
53 The signal mask is not adjusted in any manner by these routines, no system
54 calls are made, and scratch registers are not required to be retained across
55 calls.
56 .Pp
57 Since no system calls need to be made and the FP state (being scratch across
58 a procedure call) does not need to be saved or restored, these switching
59 functions are at least 10 times faster than the non-quick versions.
60 In addition, callers can setup quick contexts for cofunction chaining
61 (when one cofunction return-chains to another), and for circular cofunction
62 chaining loops, avoiding the need to save any register state at all in
63 those configurations.
64 .Pp
65 The
66 .Fn makecontext_quick
67 function
68 initializes all fields of the passed-in context except
69 .Li "ucp->uc_stack" ,
70 .Li "ucp->uc_cofunc" ,
71 and
72 .Li "ucp->uc_arg" .
73 All other structural fields will be zerod.
74 Note that
75 .Li "ucp->uc_link"
76 will also be zerod for safety.
77 .Pp
78 The caller must pre-initialize the uc_stack fields.
79 .Li "ucp->uc_cofunc" ,
80 and
81 .Li "ucp->uc_arg"
82 should be initialized prior to making any context switches.
83 This function will set the context up to call the cofunction as
84 .Li "ucp->uc_cofunc(ucp, ucp->uc_arg)" .
85 Note that this calling format is different from the non-quick context calls.
86 .Pp
87 If the cofunction returns the wrapper will automatically reinitialize
88 the context to reissue a cofunction call and then call the next
89 cofunction via
90 .Li "ucp->uc_link" .
91 If the link field is NULL, the wrapper issues an
92 .Li "exit(0)" .
93 If the linkages return to the ucontext, the cofunction call is reissued.
94 The
95 .Li "ucp->uc_cofunc" ,
96 and
97 .Li "ucp->uc_arg"
98 fields may be adjusted at any time to change the cofunction being called.
99 Using the auto-linkage feature avoids saving register state on cofunction
100 return and is the absolute quickest context switch possible, almost as
101 fast as a normal procedure call would be.
102 .Pp
103 The
104 .Fn setcontext_quick
105 function throws away the current context and switches to the target
106 context.
107 Again, the signal mask is not touched and scratch registers are not saved.
108 If you desire to switch to a signal stack ucontext you must use the
109 normal
110 .Fn setcontext
111 function and not this one.
112 This function is designed for synchronous switching only.
113 .Pp
114 The
115 .Fn swapcontext_quick
116 function saves the current register state and switches to the target
117 context.
118 This function returns when the old context is resumed.
119 Again, the signal mask is not touched and scratch registers are not saved.
120 If you desire to switch to a signal stack ucontext you must use the
121 normal
122 .Fn swapcontext
123 function and not this one.
124 It is acceptable to mix normal context functions with quick functions
125 as long as you understand the ramifications.
126 .Pp
127 There is no quick version for
128 .Fn getcontext
129 on purpose.
130 .Sh RETURN VALUES
131 These functions have no return value.
132 .Sh EXAMPLES
133 .Bd -literal
134 /*
135  * quick context test program
136  */
137 #include <sys/types.h>
138 #include <sys/stat.h>
139 #include <sys/file.h>
140 #include <ucontext.h>
141 #include <stdio.h>
142 #include <stdlib.h>
143 #include <unistd.h>
144 #include <string.h>
145 #include <assert.h>
146
147 #define LOOPS   100000000L
148
149 static void test1(ucontext_t *ucp, void *arg);
150 static void test2(ucontext_t *ucp, void *arg);
151 static void test3(ucontext_t *ucp, void *arg);
152
153 int
154 main(int ac, char **av)
155 {
156         ucontext_t ucp1;
157         ucontext_t ucp2;
158         ucontext_t ucp3;
159
160         ucp1.uc_stack.ss_sp = malloc(32768);
161         ucp1.uc_stack.ss_size = 32768;
162         ucp1.uc_cofunc = test1;
163         ucp1.uc_arg = (void *)(intptr_t)1;
164         makecontext_quick(&ucp1);
165
166         ucp2.uc_stack.ss_sp = malloc(32768);
167         ucp2.uc_stack.ss_size = 32768;
168         ucp2.uc_cofunc = test2;
169         ucp2.uc_arg = (void *)(intptr_t)2;
170         makecontext_quick(&ucp2);
171
172         ucp3.uc_stack.ss_sp = malloc(32768);
173         ucp3.uc_stack.ss_size = 32768;
174         ucp3.uc_cofunc = test3;
175         ucp3.uc_arg = (void *)(intptr_t)3;
176         makecontext_quick(&ucp3);
177
178         ucp1.uc_link = &ucp2;
179         ucp2.uc_link = &ucp3;
180         ucp3.uc_link = &ucp1;
181         setcontext_quick(&ucp1);
182 }
183
184 long global_counter;
185
186 static void
187 test1(ucontext_t *ucp, void *arg)
188 {
189         if ((intptr_t)ucp->uc_arg == 1) {
190                 printf("test1 entered for first time\en");
191                 ucp->uc_arg = (void *)(intptr_t)0;
192         }
193 }
194
195 static void
196 test2(ucontext_t *ucp, void *arg)
197 {
198         if ((intptr_t)ucp->uc_arg == 2) {
199                 printf("test2 entered for first time\en");
200                 ucp->uc_arg = (void *)(intptr_t)0;
201         }
202         ++global_counter;
203         if (global_counter > LOOPS)
204                 ucp->uc_link = NULL;    /* demonstrate documented exit(0) */
205 }
206
207 static void
208 test3(ucontext_t *ucp, void *arg)
209 {
210         /* entered only once */
211         assert((intptr_t)ucp->uc_arg == 3);
212         printf("test3 entered for first time\en");
213         printf("cycle through test1, test2, test3 %d times\en", LOOPS);
214         ucp->uc_arg = (void *)(intptr_t)0;
215
216         for (;;) {
217                 swapcontext_quick(ucp, ucp->uc_link);
218         }
219 }
220 .Ed
221 .Sh ERRORS
222 .Bl -tag -width Er
223 .It Bq Er ENOMEM
224 There is not enough stack space in
225 .Fa ucp
226 to complete the operation.
227 .El
228 .Sh SEE ALSO
229 .Xr getcontext 3 ,
230 .Xr makecontext 3 ,
231 .Xr setcontext 3 ,
232 .Xr swapcontext 3 ,
233 .Xr ucontext 3