1makecontext(3) Library Functions Manual makecontext(3)
2
3
4
6 makecontext, swapcontext - manipulate user context
7
9 Standard C library (libc, -lc)
10
12 #include <ucontext.h>
13
14 void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
15 int swapcontext(ucontext_t *restrict oucp,
16 const ucontext_t *restrict ucp);
17
19 In a System V-like environment, one has the type ucontext_t (defined in
20 <ucontext.h> and described in getcontext(3)) and the four functions
21 getcontext(3), setcontext(3), makecontext(), and swapcontext() that al‐
22 low user-level context switching between multiple threads of control
23 within a process.
24
25 The makecontext() function modifies the context pointed to by ucp
26 (which was obtained from a call to getcontext(3)). Before invoking
27 makecontext(), the caller must allocate a new stack for this context
28 and assign its address to ucp->uc_stack, and define a successor context
29 and assign its address to ucp->uc_link.
30
31 When this context is later activated (using setcontext(3) or swapcon‐
32 text()) the function func is called, and passed the series of integer
33 (int) arguments that follow argc; the caller must specify the number of
34 these arguments in argc. When this function returns, the successor
35 context is activated. If the successor context pointer is NULL, the
36 thread exits.
37
38 The swapcontext() function saves the current context in the structure
39 pointed to by oucp, and then activates the context pointed to by ucp.
40
42 When successful, swapcontext() does not return. (But we may return
43 later, in case oucp is activated, in which case it looks like swapcon‐
44 text() returns 0.) On error, swapcontext() returns -1 and sets errno
45 to indicate the error.
46
48 ENOMEM Insufficient stack space left.
49
51 For an explanation of the terms used in this section, see at‐
52 tributes(7).
53
54 ┌──────────────┬───────────────┬───────────────────────────────────────┐
55 │Interface │ Attribute │ Value │
56 ├──────────────┼───────────────┼───────────────────────────────────────┤
57 │makecontext() │ Thread safety │ MT-Safe race:ucp │
58 ├──────────────┼───────────────┼───────────────────────────────────────┤
59 │swapcontext() │ Thread safety │ MT-Safe race:oucp race:ucp │
60 └──────────────┴───────────────┴───────────────────────────────────────┘
61
63 None.
64
66 glibc 2.1. SUSv2, POSIX.1-2001. Removed in POSIX.1-2008, citing
67 portability issues, and recommending that applications be rewritten to
68 use POSIX threads instead.
69
71 The interpretation of ucp->uc_stack is just as in sigaltstack(2),
72 namely, this struct contains the start and length of a memory area to
73 be used as the stack, regardless of the direction of growth of the
74 stack. Thus, it is not necessary for the user program to worry about
75 this direction.
76
77 On architectures where int and pointer types are the same size (e.g.,
78 x86-32, where both types are 32 bits), you may be able to get away with
79 passing pointers as arguments to makecontext() following argc.
80 However, doing this is not guaranteed to be portable, is undefined
81 according to the standards, and won't work on architectures where
82 pointers are larger than ints. Nevertheless, starting with glibc 2.8,
83 glibc makes some changes to makecontext(), to permit this on some
84 64-bit architectures (e.g., x86-64).
85
87 The example program below demonstrates the use of getcontext(3),
88 makecontext(), and swapcontext(). Running the program produces the
89 following output:
90
91 $ ./a.out
92 main: swapcontext(&uctx_main, &uctx_func2)
93 func2: started
94 func2: swapcontext(&uctx_func2, &uctx_func1)
95 func1: started
96 func1: swapcontext(&uctx_func1, &uctx_func2)
97 func2: returning
98 func1: returning
99 main: exiting
100
101 Program source
102
103 #include <stdio.h>
104 #include <stdlib.h>
105 #include <ucontext.h>
106
107 static ucontext_t uctx_main, uctx_func1, uctx_func2;
108
109 #define handle_error(msg) \
110 do { perror(msg); exit(EXIT_FAILURE); } while (0)
111
112 static void
113 func1(void)
114 {
115 printf("%s: started\n", __func__);
116 printf("%s: swapcontext(&uctx_func1, &uctx_func2)\n", __func__);
117 if (swapcontext(&uctx_func1, &uctx_func2) == -1)
118 handle_error("swapcontext");
119 printf("%s: returning\n", __func__);
120 }
121
122 static void
123 func2(void)
124 {
125 printf("%s: started\n", __func__);
126 printf("%s: swapcontext(&uctx_func2, &uctx_func1)\n", __func__);
127 if (swapcontext(&uctx_func2, &uctx_func1) == -1)
128 handle_error("swapcontext");
129 printf("%s: returning\n", __func__);
130 }
131
132 int
133 main(int argc, char *argv[])
134 {
135 char func1_stack[16384];
136 char func2_stack[16384];
137
138 if (getcontext(&uctx_func1) == -1)
139 handle_error("getcontext");
140 uctx_func1.uc_stack.ss_sp = func1_stack;
141 uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
142 uctx_func1.uc_link = &uctx_main;
143 makecontext(&uctx_func1, func1, 0);
144
145 if (getcontext(&uctx_func2) == -1)
146 handle_error("getcontext");
147 uctx_func2.uc_stack.ss_sp = func2_stack;
148 uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
149 /* Successor context is f1(), unless argc > 1 */
150 uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
151 makecontext(&uctx_func2, func2, 0);
152
153 printf("%s: swapcontext(&uctx_main, &uctx_func2)\n", __func__);
154 if (swapcontext(&uctx_main, &uctx_func2) == -1)
155 handle_error("swapcontext");
156
157 printf("%s: exiting\n", __func__);
158 exit(EXIT_SUCCESS);
159 }
160
162 sigaction(2), sigaltstack(2), sigprocmask(2), getcontext(3),
163 sigsetjmp(3)
164
165
166
167Linux man-pages 6.05 2023-07-20 makecontext(3)