Merge branch 'vendor/DIFFUTILS'
[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 ERRORS
133 .Bl -tag -width Er
134 .It Bq Er ENOMEM
135 There is not enough stack space in
136 .Fa ucp
137 to complete the operation.
138 .El
139 .Sh EXAMPLE
140 .Bd -literal
141 /*
142  * quick context test program
143  */
144 #include <sys/types.h>
145 #include <sys/stat.h>
146 #include <sys/file.h>
147 #include <ucontext.h>
148 #include <stdio.h>
149 #include <stdlib.h>
150 #include <unistd.h>
151 #include <string.h>
152 #include <assert.h>
153
154 #define LOOPS   100000000L
155
156 static void test1(ucontext_t *ucp, void *arg);
157 static void test2(ucontext_t *ucp, void *arg);
158 static void test3(ucontext_t *ucp, void *arg);
159
160 int
161 main(int ac, char **av)
162 {
163         ucontext_t ucp1;
164         ucontext_t ucp2;
165         ucontext_t ucp3;
166
167         ucp1.uc_stack.ss_sp = malloc(32768);
168         ucp1.uc_stack.ss_size = 32768;
169         ucp1.uc_cofunc = test1;
170         ucp1.uc_arg = (void *)(intptr_t)1;
171         makecontext_quick(&ucp1);
172
173         ucp2.uc_stack.ss_sp = malloc(32768);
174         ucp2.uc_stack.ss_size = 32768;
175         ucp2.uc_cofunc = test2;
176         ucp2.uc_arg = (void *)(intptr_t)2;
177         makecontext_quick(&ucp2);
178
179         ucp3.uc_stack.ss_sp = malloc(32768);
180         ucp3.uc_stack.ss_size = 32768;
181         ucp3.uc_cofunc = test3;
182         ucp3.uc_arg = (void *)(intptr_t)3;
183         makecontext_quick(&ucp3);
184
185         ucp1.uc_link = &ucp2;
186         ucp2.uc_link = &ucp3;
187         ucp3.uc_link = &ucp1;
188         setcontext_quick(&ucp1);
189 }
190
191 long global_counter;
192
193 static void
194 test1(ucontext_t *ucp, void *arg)
195 {
196         if ((intptr_t)ucp->uc_arg == 1) {
197                 printf("test1 entered for first time\en");
198                 ucp->uc_arg = (void *)(intptr_t)0;
199         }
200 }
201
202 static void
203 test2(ucontext_t *ucp, void *arg)
204 {
205         if ((intptr_t)ucp->uc_arg == 2) {
206                 printf("test2 entered for first time\en");
207                 ucp->uc_arg = (void *)(intptr_t)0;
208         }
209         ++global_counter;
210         if (global_counter > LOOPS)
211                 ucp->uc_link = NULL;    /* demonstrate documented exit(0) */
212 }
213
214 static void
215 test3(ucontext_t *ucp, void *arg)
216 {
217         /* entered only once */
218         assert((intptr_t)ucp->uc_arg == 3);
219         printf("test3 entered for first time\en");
220         printf("cycle through test1, test2, test3 %d times\en", LOOPS);
221         ucp->uc_arg = (void *)(intptr_t)0;
222
223         for (;;) {
224                 swapcontext_quick(ucp, ucp->uc_link);
225         }
226 }
227 .Ed
228 .Sh SEE ALSO
229 .Xr getcontext 3 ,
230 .Xr makecontext 3 ,
231 .Xr setcontext 3 ,
232 .Xr swapcontext 3 ,
233 .Xr ucontext 3