]>
Commit | Line | Data |
---|---|---|
243d656f | 1 | .\" Copyright (C) 2001 Andries Brouwer (aeb@cwi.nl) |
c343e74c | 2 | .\" and Copyright (C) 2006 Michael Kerrisk <mtk.manpages@gmail.com> |
fea681da | 3 | .\" |
5fbde956 | 4 | .\" SPDX-License-Identifier: Linux-man-pages-copyleft |
9b21ca97 | 5 | .\" |
c343e74c | 6 | .\" 2006-08-02, mtk, Added example program |
fea681da | 7 | .\" |
4c1c5274 | 8 | .TH makecontext 3 (date) "Linux man-pages (unreleased)" |
fea681da MK |
9 | .SH NAME |
10 | makecontext, swapcontext \- manipulate user context | |
26fd6813 AC |
11 | .SH LIBRARY |
12 | Standard C library | |
8fc3b2cf | 13 | .RI ( libc ", " \-lc ) |
fea681da | 14 | .SH SYNOPSIS |
15d65653 | 15 | .nf |
fea681da | 16 | .B #include <ucontext.h> |
68e4db0a | 17 | .PP |
e64e5812 AC |
18 | .BI "void makecontext(ucontext_t *" ucp ", void (*" func ")(), int " argc \ |
19 | ", ...);" | |
20 | .BI "int swapcontext(ucontext_t *restrict " oucp , | |
21 | .BI " const ucontext_t *restrict " ucp ); | |
15d65653 | 22 | .fi |
fea681da | 23 | .SH DESCRIPTION |
6430ba7a MK |
24 | In a System V-like environment, one has the type |
25 | .I ucontext_t | |
26 | (defined in | |
fea681da | 27 | .I <ucontext.h> |
6430ba7a MK |
28 | and described in |
29 | .BR getcontext (3)) | |
fea681da | 30 | and the four functions |
fb872845 MK |
31 | .BR getcontext (3), |
32 | .BR setcontext (3), | |
d556548b | 33 | .BR makecontext (), |
60a90ecd MK |
34 | and |
35 | .BR swapcontext () | |
36 | that allow user-level context switching | |
fea681da | 37 | between multiple threads of control within a process. |
dd3568a1 | 38 | .PP |
60a90ecd MK |
39 | The |
40 | .BR makecontext () | |
41 | function modifies the context pointed to | |
42 | by \fIucp\fP (which was obtained from a call to | |
fb872845 | 43 | .BR getcontext (3)). |
60a90ecd MK |
44 | Before invoking |
45 | .BR makecontext (), | |
46 | the caller must allocate a new stack | |
94e9d9fe | 47 | for this context and assign its address to \fIucp\->uc_stack\fP, |
3333513d | 48 | and define a successor context and |
94e9d9fe | 49 | assign its address to \fIucp\->uc_link\fP. |
847e0d88 | 50 | .PP |
60a90ecd | 51 | When this context is later activated (using |
fb872845 | 52 | .BR setcontext (3) |
60a90ecd MK |
53 | or |
54 | .BR swapcontext ()) | |
55 | the function \fIfunc\fP is called, | |
c13182ef | 56 | and passed the series of integer |
3333513d | 57 | .RI ( int ) |
53a9ef80 MK |
58 | arguments that follow |
59 | .IR argc ; | |
60 | the caller must specify the number of these arguments in | |
61 | .IR argc . | |
c13182ef | 62 | When this function returns, the successor context is activated. |
53a9ef80 | 63 | If the successor context pointer is NULL, the thread exits. |
dd3568a1 | 64 | .PP |
60a90ecd MK |
65 | The |
66 | .BR swapcontext () | |
67 | function saves the current context in | |
fea681da MK |
68 | the structure pointed to by \fIoucp\fP, and then activates the |
69 | context pointed to by \fIucp\fP. | |
47297adb | 70 | .SH RETURN VALUE |
60a90ecd MK |
71 | When successful, |
72 | .BR swapcontext () | |
c13182ef MK |
73 | does not return. |
74 | (But we may return later, in case \fIoucp\fP is | |
60a90ecd MK |
75 | activated, in which case it looks like |
76 | .BR swapcontext () | |
77 | returns 0.) | |
78 | On error, | |
79 | .BR swapcontext () | |
f6a4078b MK |
80 | returns \-1 and sets |
81 | .I errno | |
82 | to indicate the error. | |
fea681da MK |
83 | .SH ERRORS |
84 | .TP | |
85 | .B ENOMEM | |
86 | Insufficient stack space left. | |
c343e74c MK |
87 | .SH VERSIONS |
88 | .BR makecontext () | |
89 | and | |
90 | .BR swapcontext () | |
91 | are provided in glibc since version 2.1. | |
e3de721c | 92 | .SH ATTRIBUTES |
7a080b8e PH |
93 | For an explanation of the terms used in this section, see |
94 | .BR attributes (7). | |
c466875e MK |
95 | .ad l |
96 | .nh | |
7a080b8e PH |
97 | .TS |
98 | allbox; | |
b32feea5 | 99 | lb lb lbx |
7a080b8e PH |
100 | l l l. |
101 | Interface Attribute Value | |
102 | T{ | |
0a585c22 | 103 | .BR makecontext () |
b32feea5 MK |
104 | T} Thread safety T{ |
105 | MT-Safe race:ucp | |
106 | T} | |
0a585c22 | 107 | T{ |
e3de721c | 108 | .BR swapcontext () |
b32feea5 MK |
109 | T} Thread safety T{ |
110 | MT-Safe race:oucp race:ucp | |
111 | T} | |
7a080b8e | 112 | .TE |
c466875e MK |
113 | .hy |
114 | .ad | |
115 | .sp 1 | |
3113c7f3 | 116 | .SH STANDARDS |
2b2581ee | 117 | SUSv2, POSIX.1-2001. |
6a8e41e9 MK |
118 | POSIX.1-2008 removes the specifications of |
119 | .BR makecontext () | |
120 | and | |
867a8f5d MK |
121 | .BR swapcontext (), |
122 | citing portability issues, and | |
123 | recommending that applications be rewritten to use POSIX threads instead. | |
fea681da | 124 | .SH NOTES |
94e9d9fe | 125 | The interpretation of \fIucp\->uc_stack\fP is just as in |
fea681da | 126 | .BR sigaltstack (2), |
53a9ef80 MK |
127 | namely, this struct contains the start and length of a memory area |
128 | to be used as the stack, regardless of the direction of growth of | |
c13182ef | 129 | the stack. |
53a9ef80 | 130 | Thus, it is not necessary for the user program to |
fea681da | 131 | worry about this direction. |
847e0d88 | 132 | .PP |
7acf73dc MK |
133 | On architectures where |
134 | .I int | |
135 | and pointer types are the same size | |
136 | (e.g., x86-32, where both types are 32 bits), | |
137 | you may be able to get away with passing pointers as arguments to | |
138 | .BR makecontext () | |
139 | following | |
140 | .IR argc . | |
141 | However, doing this is not guaranteed to be portable, | |
142 | is undefined according to the standards, | |
143 | and won't work on architectures where pointers are larger than | |
144 | .IR int s. | |
515ad542 | 145 | Nevertheless, starting with version 2.8, glibc makes some changes to |
27d47e71 | 146 | .BR makecontext (), |
7acf73dc | 147 | to permit this on some 64-bit architectures (e.g., x86-64). |
a14af333 | 148 | .SH EXAMPLES |
3333513d | 149 | The example program below demonstrates the use of |
fb872845 | 150 | .BR getcontext (3), |
3333513d MK |
151 | .BR makecontext (), |
152 | and | |
153 | .BR swapcontext (). | |
154 | Running the program produces the following output: | |
e646a1ba | 155 | .PP |
a08ea57c | 156 | .in +4n |
e646a1ba | 157 | .EX |
b43a3b30 | 158 | .RB "$" " ./a.out" |
3333513d MK |
159 | main: swapcontext(&uctx_main, &uctx_func2) |
160 | func2: started | |
161 | func2: swapcontext(&uctx_func2, &uctx_func1) | |
162 | func1: started | |
163 | func1: swapcontext(&uctx_func1, &uctx_func2) | |
164 | func2: returning | |
165 | func1: returning | |
166 | main: exiting | |
b8302363 | 167 | .EE |
a08ea57c | 168 | .in |
9c330504 | 169 | .SS Program source |
d84d0300 | 170 | \& |
b0b6ab4e | 171 | .\" SRC BEGIN (makecontext.c) |
e7d0bb47 | 172 | .EX |
3333513d MK |
173 | #include <stdio.h> |
174 | #include <stdlib.h> | |
ad3868f0 | 175 | #include <ucontext.h> |
3333513d MK |
176 | |
177 | static ucontext_t uctx_main, uctx_func1, uctx_func2; | |
178 | ||
d1a71985 | 179 | #define handle_error(msg) \e |
6a578b88 | 180 | do { perror(msg); exit(EXIT_FAILURE); } while (0) |
3333513d MK |
181 | |
182 | static void | |
183 | func1(void) | |
184 | { | |
4a41b9b5 AC |
185 | printf("%s: started\en", __func__); |
186 | printf("%s: swapcontext(&uctx_func1, &uctx_func2)\en", __func__); | |
29059a65 | 187 | if (swapcontext(&uctx_func1, &uctx_func2) == \-1) |
6a578b88 | 188 | handle_error("swapcontext"); |
4a41b9b5 | 189 | printf("%s: returning\en", __func__); |
3333513d MK |
190 | } |
191 | ||
192 | static void | |
193 | func2(void) | |
194 | { | |
4a41b9b5 AC |
195 | printf("%s: started\en", __func__); |
196 | printf("%s: swapcontext(&uctx_func2, &uctx_func1)\en", __func__); | |
29059a65 | 197 | if (swapcontext(&uctx_func2, &uctx_func1) == \-1) |
6a578b88 | 198 | handle_error("swapcontext"); |
4a41b9b5 | 199 | printf("%s: returning\en", __func__); |
3333513d MK |
200 | } |
201 | ||
202 | int | |
203 | main(int argc, char *argv[]) | |
204 | { | |
205 | char func1_stack[16384]; | |
206 | char func2_stack[16384]; | |
207 | ||
29059a65 | 208 | if (getcontext(&uctx_func1) == \-1) |
6a578b88 | 209 | handle_error("getcontext"); |
3333513d MK |
210 | uctx_func1.uc_stack.ss_sp = func1_stack; |
211 | uctx_func1.uc_stack.ss_size = sizeof(func1_stack); | |
212 | uctx_func1.uc_link = &uctx_main; | |
213 | makecontext(&uctx_func1, func1, 0); | |
214 | ||
29059a65 | 215 | if (getcontext(&uctx_func2) == \-1) |
6a578b88 | 216 | handle_error("getcontext"); |
3333513d MK |
217 | uctx_func2.uc_stack.ss_sp = func2_stack; |
218 | uctx_func2.uc_stack.ss_size = sizeof(func2_stack); | |
219 | /* Successor context is f1(), unless argc > 1 */ | |
220 | uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1; | |
221 | makecontext(&uctx_func2, func2, 0); | |
222 | ||
4a41b9b5 | 223 | printf("%s: swapcontext(&uctx_main, &uctx_func2)\en", __func__); |
29059a65 | 224 | if (swapcontext(&uctx_main, &uctx_func2) == \-1) |
6a578b88 | 225 | handle_error("swapcontext"); |
3333513d | 226 | |
4a41b9b5 | 227 | printf("%s: exiting\en", __func__); |
3333513d MK |
228 | exit(EXIT_SUCCESS); |
229 | } | |
e7d0bb47 | 230 | .EE |
b0b6ab4e | 231 | .\" SRC END |
47297adb | 232 | .SH SEE ALSO |
fea681da MK |
233 | .BR sigaction (2), |
234 | .BR sigaltstack (2), | |
235 | .BR sigprocmask (2), | |
fb872845 | 236 | .BR getcontext (3), |
fea681da | 237 | .BR sigsetjmp (3) |