]>
Commit | Line | Data |
---|---|---|
3194c8ce AB |
1 | /* |
2 | * sigaltstack coroutine initialization code | |
3 | * | |
4 | * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> | |
5 | * Copyright (C) 2011 Kevin Wolf <kwolf@redhat.com> | |
6 | * Copyright (C) 2012 Alex Barcelo <abarcelo@ac.upc.edu> | |
7 | ** This file is partly based on pth_mctx.c, from the GNU Portable Threads | |
8 | ** Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com> | |
9 | * | |
10 | * This library is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU Lesser General Public | |
12 | * License as published by the Free Software Foundation; either | |
13 | * version 2.1 of the License, or (at your option) any later version. | |
14 | * | |
15 | * This library is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | * Lesser General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU Lesser General Public | |
21 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
22 | */ | |
23 | ||
24 | /* XXX Is there a nicer way to disable glibc's stack check for longjmp? */ | |
25 | #ifdef _FORTIFY_SOURCE | |
26 | #undef _FORTIFY_SOURCE | |
27 | #endif | |
aafd7584 | 28 | #include "qemu/osdep.h" |
3194c8ce | 29 | #include <pthread.h> |
10817bf0 | 30 | #include "qemu/coroutine_int.h" |
3194c8ce | 31 | |
ff76097a DB |
32 | #ifdef CONFIG_SAFESTACK |
33 | #error "SafeStack is not compatible with code run in alternate signal stacks" | |
34 | #endif | |
35 | ||
3194c8ce AB |
36 | typedef struct { |
37 | Coroutine base; | |
38 | void *stack; | |
2f4aa232 | 39 | size_t stack_size; |
6ab7e546 | 40 | sigjmp_buf env; |
be87a393 | 41 | } CoroutineSigAltStack; |
3194c8ce AB |
42 | |
43 | /** | |
44 | * Per-thread coroutine bookkeeping | |
45 | */ | |
46 | typedef struct { | |
47 | /** Currently executing coroutine */ | |
48 | Coroutine *current; | |
49 | ||
50 | /** The default coroutine */ | |
be87a393 | 51 | CoroutineSigAltStack leader; |
3194c8ce AB |
52 | |
53 | /** Information for the signal handler (trampoline) */ | |
6ab7e546 | 54 | sigjmp_buf tr_reenter; |
3194c8ce AB |
55 | volatile sig_atomic_t tr_called; |
56 | void *tr_handler; | |
57 | } CoroutineThreadState; | |
58 | ||
59 | static pthread_key_t thread_state_key; | |
60 | ||
61 | static CoroutineThreadState *coroutine_get_thread_state(void) | |
62 | { | |
63 | CoroutineThreadState *s = pthread_getspecific(thread_state_key); | |
64 | ||
65 | if (!s) { | |
66 | s = g_malloc0(sizeof(*s)); | |
67 | s->current = &s->leader.base; | |
68 | pthread_setspecific(thread_state_key, s); | |
69 | } | |
70 | return s; | |
71 | } | |
72 | ||
73 | static void qemu_coroutine_thread_cleanup(void *opaque) | |
74 | { | |
75 | CoroutineThreadState *s = opaque; | |
76 | ||
77 | g_free(s); | |
78 | } | |
79 | ||
3194c8ce AB |
80 | static void __attribute__((constructor)) coroutine_init(void) |
81 | { | |
82 | int ret; | |
83 | ||
84 | ret = pthread_key_create(&thread_state_key, qemu_coroutine_thread_cleanup); | |
85 | if (ret != 0) { | |
86 | fprintf(stderr, "unable to create leader key: %s\n", strerror(errno)); | |
87 | abort(); | |
88 | } | |
89 | } | |
90 | ||
91 | /* "boot" function | |
92 | * This is what starts the coroutine, is called from the trampoline | |
93 | * (from the signal handler when it is not signal handling, read ahead | |
94 | * for more information). | |
95 | */ | |
be87a393 | 96 | static void coroutine_bootstrap(CoroutineSigAltStack *self, Coroutine *co) |
3194c8ce AB |
97 | { |
98 | /* Initialize longjmp environment and switch back the caller */ | |
6ab7e546 PM |
99 | if (!sigsetjmp(self->env, 0)) { |
100 | siglongjmp(*(sigjmp_buf *)co->entry_arg, 1); | |
3194c8ce AB |
101 | } |
102 | ||
103 | while (true) { | |
104 | co->entry(co->entry_arg); | |
105 | qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE); | |
106 | } | |
107 | } | |
108 | ||
109 | /* | |
110 | * This is used as the signal handler. This is called with the brand new stack | |
111 | * (thanks to sigaltstack). We have to return, given that this is a signal | |
112 | * handler and the sigmask and some other things are changed. | |
113 | */ | |
114 | static void coroutine_trampoline(int signal) | |
115 | { | |
be87a393 | 116 | CoroutineSigAltStack *self; |
3194c8ce AB |
117 | Coroutine *co; |
118 | CoroutineThreadState *coTS; | |
119 | ||
120 | /* Get the thread specific information */ | |
121 | coTS = coroutine_get_thread_state(); | |
122 | self = coTS->tr_handler; | |
123 | coTS->tr_called = 1; | |
124 | co = &self->base; | |
125 | ||
126 | /* | |
127 | * Here we have to do a bit of a ping pong between the caller, given that | |
128 | * this is a signal handler and we have to do a return "soon". Then the | |
6ab7e546 | 129 | * caller can reestablish everything and do a siglongjmp here again. |
3194c8ce | 130 | */ |
6ab7e546 | 131 | if (!sigsetjmp(coTS->tr_reenter, 0)) { |
3194c8ce AB |
132 | return; |
133 | } | |
134 | ||
135 | /* | |
6ab7e546 | 136 | * Ok, the caller has siglongjmp'ed back to us, so now prepare |
3194c8ce AB |
137 | * us for the real machine state switching. We have to jump |
138 | * into another function here to get a new stack context for | |
139 | * the auto variables (which have to be auto-variables | |
140 | * because the start of the thread happens later). Else with | |
141 | * PIC (i.e. Position Independent Code which is used when PTH | |
142 | * is built as a shared library) most platforms would | |
143 | * horrible core dump as experience showed. | |
144 | */ | |
145 | coroutine_bootstrap(self, co); | |
146 | } | |
147 | ||
40239784 | 148 | Coroutine *qemu_coroutine_new(void) |
3194c8ce | 149 | { |
be87a393 | 150 | CoroutineSigAltStack *co; |
3194c8ce AB |
151 | CoroutineThreadState *coTS; |
152 | struct sigaction sa; | |
153 | struct sigaction osa; | |
2ad2210a PM |
154 | stack_t ss; |
155 | stack_t oss; | |
3194c8ce AB |
156 | sigset_t sigs; |
157 | sigset_t osigs; | |
7f151e6f | 158 | sigjmp_buf old_env; |
f4be8225 | 159 | static pthread_mutex_t sigusr2_mutex = PTHREAD_MUTEX_INITIALIZER; |
3194c8ce AB |
160 | |
161 | /* The way to manipulate stack is with the sigaltstack function. We | |
162 | * prepare a stack, with it delivering a signal to ourselves and then | |
6ab7e546 | 163 | * put sigsetjmp/siglongjmp where needed. |
3194c8ce AB |
164 | * This has been done keeping coroutine-ucontext as a model and with the |
165 | * pth ideas (GNU Portable Threads). See coroutine-ucontext for the basics | |
166 | * of the coroutines and see pth_mctx.c (from the pth project) for the | |
167 | * sigaltstack way of manipulating stacks. | |
168 | */ | |
169 | ||
170 | co = g_malloc0(sizeof(*co)); | |
2f4aa232 PL |
171 | co->stack_size = COROUTINE_STACK_SIZE; |
172 | co->stack = qemu_alloc_stack(&co->stack_size); | |
3194c8ce AB |
173 | co->base.entry_arg = &old_env; /* stash away our jmp_buf */ |
174 | ||
175 | coTS = coroutine_get_thread_state(); | |
176 | coTS->tr_handler = co; | |
177 | ||
178 | /* | |
179 | * Preserve the SIGUSR2 signal state, block SIGUSR2, | |
180 | * and establish our signal handler. The signal will | |
181 | * later transfer control onto the signal stack. | |
182 | */ | |
183 | sigemptyset(&sigs); | |
184 | sigaddset(&sigs, SIGUSR2); | |
185 | pthread_sigmask(SIG_BLOCK, &sigs, &osigs); | |
186 | sa.sa_handler = coroutine_trampoline; | |
187 | sigfillset(&sa.sa_mask); | |
188 | sa.sa_flags = SA_ONSTACK; | |
f4be8225 HR |
189 | |
190 | /* | |
191 | * sigaction() is a process-global operation. We must not run | |
192 | * this code in multiple threads at once. | |
193 | */ | |
194 | pthread_mutex_lock(&sigusr2_mutex); | |
3194c8ce AB |
195 | if (sigaction(SIGUSR2, &sa, &osa) != 0) { |
196 | abort(); | |
197 | } | |
198 | ||
199 | /* | |
200 | * Set the new stack. | |
201 | */ | |
202 | ss.ss_sp = co->stack; | |
2f4aa232 | 203 | ss.ss_size = co->stack_size; |
3194c8ce AB |
204 | ss.ss_flags = 0; |
205 | if (sigaltstack(&ss, &oss) < 0) { | |
206 | abort(); | |
207 | } | |
208 | ||
209 | /* | |
210 | * Now transfer control onto the signal stack and set it up. | |
6ab7e546 | 211 | * It will return immediately via "return" after the sigsetjmp() |
3194c8ce AB |
212 | * was performed. Be careful here with race conditions. The |
213 | * signal can be delivered the first time sigsuspend() is | |
214 | * called. | |
215 | */ | |
216 | coTS->tr_called = 0; | |
99b5beba | 217 | pthread_kill(pthread_self(), SIGUSR2); |
3194c8ce AB |
218 | sigfillset(&sigs); |
219 | sigdelset(&sigs, SIGUSR2); | |
220 | while (!coTS->tr_called) { | |
221 | sigsuspend(&sigs); | |
222 | } | |
223 | ||
224 | /* | |
225 | * Inform the system that we are back off the signal stack by | |
226 | * removing the alternative signal stack. Be careful here: It | |
227 | * first has to be disabled, before it can be removed. | |
228 | */ | |
229 | sigaltstack(NULL, &ss); | |
230 | ss.ss_flags = SS_DISABLE; | |
231 | if (sigaltstack(&ss, NULL) < 0) { | |
232 | abort(); | |
233 | } | |
234 | sigaltstack(NULL, &ss); | |
235 | if (!(oss.ss_flags & SS_DISABLE)) { | |
236 | sigaltstack(&oss, NULL); | |
237 | } | |
238 | ||
239 | /* | |
240 | * Restore the old SIGUSR2 signal handler and mask | |
241 | */ | |
242 | sigaction(SIGUSR2, &osa, NULL); | |
f4be8225 HR |
243 | pthread_mutex_unlock(&sigusr2_mutex); |
244 | ||
3194c8ce AB |
245 | pthread_sigmask(SIG_SETMASK, &osigs, NULL); |
246 | ||
247 | /* | |
248 | * Now enter the trampoline again, but this time not as a signal | |
249 | * handler. Instead we jump into it directly. The functionally | |
a31f0531 | 250 | * redundant ping-pong pointer arithmetic is necessary to avoid |
3194c8ce AB |
251 | * type-conversion warnings related to the `volatile' qualifier and |
252 | * the fact that `jmp_buf' usually is an array type. | |
253 | */ | |
6ab7e546 PM |
254 | if (!sigsetjmp(old_env, 0)) { |
255 | siglongjmp(coTS->tr_reenter, 1); | |
3194c8ce AB |
256 | } |
257 | ||
258 | /* | |
259 | * Ok, we returned again, so now we're finished | |
260 | */ | |
261 | ||
262 | return &co->base; | |
263 | } | |
264 | ||
3194c8ce AB |
265 | void qemu_coroutine_delete(Coroutine *co_) |
266 | { | |
be87a393 | 267 | CoroutineSigAltStack *co = DO_UPCAST(CoroutineSigAltStack, base, co_); |
3194c8ce | 268 | |
2f4aa232 | 269 | qemu_free_stack(co->stack, co->stack_size); |
3194c8ce AB |
270 | g_free(co); |
271 | } | |
272 | ||
273 | CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_, | |
274 | CoroutineAction action) | |
275 | { | |
be87a393 PL |
276 | CoroutineSigAltStack *from = DO_UPCAST(CoroutineSigAltStack, base, from_); |
277 | CoroutineSigAltStack *to = DO_UPCAST(CoroutineSigAltStack, base, to_); | |
3194c8ce AB |
278 | CoroutineThreadState *s = coroutine_get_thread_state(); |
279 | int ret; | |
280 | ||
281 | s->current = to_; | |
282 | ||
6ab7e546 | 283 | ret = sigsetjmp(from->env, 0); |
3194c8ce | 284 | if (ret == 0) { |
6ab7e546 | 285 | siglongjmp(to->env, action); |
3194c8ce AB |
286 | } |
287 | return ret; | |
288 | } | |
289 | ||
290 | Coroutine *qemu_coroutine_self(void) | |
291 | { | |
292 | CoroutineThreadState *s = coroutine_get_thread_state(); | |
293 | ||
294 | return s->current; | |
295 | } | |
296 | ||
297 | bool qemu_in_coroutine(void) | |
298 | { | |
299 | CoroutineThreadState *s = pthread_getspecific(thread_state_key); | |
300 | ||
301 | return s && s->current->caller; | |
302 | } | |
303 |